我有一些看起来像的代码:
class Parent {
private Intermediate intermediateContainer;
public Intermediate getIntermediate();
}
class Intermediate {
private Child child;
public Child getChild() {...}
public void intermediateOp();
}
class Child {
public void something();
public void somethingElse();
}
class Client {
private Parent parent;
public void something() {
parent.getIntermediate().getChild().something();
}
public void somethingElse() {
parent.getIntermediate().getChild().somethingElse();
}
public void intermediate() {
parent.getIntermediate().intermediateOp();
}
}
据我所知,这是“功能羡慕”代码气味的一个例子。问题是,解决它的最佳方法是什么?我的第一直觉是将这三种方法放在父母身上:
parent.something();
parent.somethingElse();
parent.intermediateOp();
...但我觉得这样重复代码,并且弄乱了Parent类的API(已经很忙)。
我是否要存储getIntermediate()和/或getChild()的结果,并保留对这些对象的引用?
答案 0 :(得分:10)
这不完全是特征嫉妒,但更多的是这些类之间的高耦合问题,并且明确违反了得墨忒耳法http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/general-formulation.html。你首先想到的方法直接在父母身上使用是一个很好的方法。客户端不应该像这样通过堆栈调用。
如果您担心父母太忙,也许您的功能太多,应该分成一些较小的类。课程应该是单一目的。
答案 1 :(得分:5)
根据我的经验,做你的建议(让所有的方法只调用“下一级别”)将有助于阐明你应该做的API的变化。所以,是的,即使它混乱了你的API,也要做出这些改变,你可能会发现处理问题的适当方法。
“事实”是指某个客户应该拥有(或想拥有)其他东西的东西。这意味着要么其他东西的功能处于错误的位置,要么就是请求该功能的东西位于错误的位置。遗憾的是,如果没有更全面的代码,很难给出具体的例子。
然而,当您最终意识到“问题”是什么时,解决方案可能不那么容易实现。这是一个无赖,但保持良好的斗争并重构该解决方案无论如何!
答案 2 :(得分:3)
谁在访问Client
?您是否需要保持其parent
私有,或者您是否应该公开它以便调用代码可以导航到所需功能所在的位置?
如果您担心完全暴露parent
,另一个选择是从Parent
中提取界面并从Client
公开。