正如Dancrumb上面所说,我认为法律的理念是确保人们在适当的级别访问对象。
想象一下,我们的Band
班级模拟了乐队办公室的前台。它的工作是充当乐队成员的 PA 并与任何想与乐队互动的人打交道。
现在假设我们有一位来自公关公司的巡演发起人,他想为他们的下一次巡演整理一些公关材料。我们可以用一个类来模拟他:
class TourPromoter {
public String makePosterText(Band band) {
String guitaristsName = band.getGuitarist().getName();
String drummersName = band.getDrummer().getName();
String singersName = band.getSinger().getName();
StringBuilder posterText = new StringBuilder();
posterText.append(band.getName()
posterText.append(" featuring: ");
posterText.append(guitaristsName);
posterText.append(", ");
posterText.append(singersName);
posterText.append(", ")
posterText.append(drummersName);
posterText.append(", ")
posterText.append("Tickets £50.");
return posterText.toString();
}
}
在现实生活中,这相当于旅游发起人打电话给办公室并说:
可以说 PA 很快就会被解雇。大多数通情达理的人会问“你不能为我们处理那个电话吗?”
我们可以有一种getGuitaristsName()
方法,从技术上讲,它会尊重 Demeter 法则,但我们仍然要求我们的TourPromoter
班级记住关于乐队的细节——即他们有一个吉他手——而这些信息应该真正属于乐队本身。
为了确保我们以合理的方式引入方法,我们需要查看巡演发起人实际上在寻找什么——即所有乐队成员的姓名。如果我们在代码中对该方法进行建模,它为我们提供了更大的灵活性,可以在以后进行更改,Band
甚至无需触摸TourPromoter
:
public class Band {
private Singer singer;
private Drummer drummer;
private Guitarist guitarist;
public String[] getMembers() {
return {singer.getName(), drummer.getName(), guitarist.getName()};
}
}
public class TourPromoter {
public String makePosterText(Band band) {
StringBuilder posterText = new StringBuilder();
posterText.append(band.getName());
posterText.append(" featuring: ");
for(String member: band.getMembers()) {
posterText.append(member);
posterText.append(", ");
}
posterText.append("Tickets: £50");
return posterText.toString();
}
}
如果我们现在添加一个 Bassist 或 KeyboardPlayer,则只有 Band 类需要知道区别,而 Tour Promoter 不需要更改。这意味着我们现在也尊重单一职责原则——即我们的makePosterText()
方法只需要在我们改变海报格式时改变,而不是在乐队改变时。
我不认为得墨忒耳法则会告诉你需要采用哪种方法才能以最好的方式(例如getMembers()
,而不是getGuitaristsName()
上面)满足原则,我认为你是对的——它确实向你展示了当事情坏了,但不一定如何修复它们。不过,牢记 LoD 意味着您要留意违规行为,然后可以通过其他设计原则(如 SRP)的组合来修复这些违规行为。