坏味道——过度耦合的消息链(Message Chains)
特征
消息链的形式类似于:obj.getA().getB().getC()
。
问题原因
如果你看到用户向一个对象请求另一个对象,然后再向后者请求另一个对象,然后再请求另一个对象……这就是消息链。实际代码中你看到的可能是一长串getThis()或一长串临时变量。采取这种方式,意味客户代码将与查找过程中的导航紧密耦合。一旦对象间关系发生任何变化,客户端就不得不做出相应的修改。
解决方法
- 可以运用
隐藏委托关系(Hide Delegate)
删除一个消息链。
- 有时更好的选择是:先观察消息链最终得到的对象是用来干什么的。看看能否以
提炼函数(Extract Method)
把使用该对象的代码提炼到一个独立函数中,再运用搬移函数(Move Method)
把这个函数推入消息链。
收益
- 能减少链中类之间的依赖。
- 能减少代码量。
何时忽略
- 过于侵略性的委托可能会使程序员难以理解功能是如何触发的。
重构方法说明
隐藏委托关系(Hide Delegate)
问题
客户通过一个委托类来调用另一个对象。
解决
在服务类上建立客户所需的所有函数,用以隐藏委托关系。
提炼函数(Extract Method)
问题
你有一段代码可以组织在一起。
void printOwing() {
printBanner();
//print details
System.out.println("name: " + name);
System.out.println("amount: " + getOutstanding());
}
解决
移动这段代码到一个新的函数中,使用函数的调用来替代老代码。
void printOwing() {
printBanner();
printDetails(getOutstanding());
}
void printDetails(double outstanding) {
System.out.println("name: " + name);
System.out.println("amount: " + outstanding);
}
搬移函数(Move Method)
问题
你的程序中,有个函数与其所驻类之外的另一个类进行更多交流:调用后者,或被后者调用。
解决
在该函数最常引用的类中建立一个有着类似行为的新函数。将旧函数变成一个单纯的委托函数,或是旧函数完全移除。
引申阅读
欢迎继续阅读 代码的症与药 系列文章。