重构第七章——在对象之间搬移特性

  • Post author:
  • Post category:其他


针对对象的重构,解决

把责任放在哪里

的问题,主要8个手段:函数搬家、字段搬家、当类承担过多责任时提取新类(反之一个类不太有责任时就是删之,将类内联化)、利用委托或代理作中间人(反之就是移除中间人)、无法修改类时的扩增方法(两种)。

1、方法搬家

A类和B类,A类中的某个方法中的逻辑依赖B类中的字段,可以考虑将这个方法移到B中。如果这个方法还需要A中的字段,可以将作为参数传入。

2、字段搬家

A类和B类,将A中的某个字段搬家到B类后,A类需要仍然保持对这个字段的引用关系,则A类可以通过引用B对象,然后通过B对象的getXXX来获取这个字段。

3、提取新类

将一个类A中的几个字段,一并移动到一个新创建的类B中。原来的类A持有对新类B对象的引用,A就可以保持对移动的字段的访问。是否公开这个新类B是一个问题,因为如果公开了B类,那么用户通过A类对象得到了B对象,就可以修改B对象的字段,这一操作会失去控制,所以是否公开需要依据实际情况慎重考虑。

4、类内联化

A类和B类,比如通过重构将B类的责任(体现在字段和方法上)差不多移完了,也就是B类不在承担足够的责任,B类也就应该被废了,如果A类是B类的最频繁使用者,则可将B中的字段放到A中,删B。

5、利用代理

类A、类B和类C,B类持有C类对象引用,A访问C可以,通过访问B来实现,而不是直接访问C,这样就降低了A和C的耦合,这种关系就叫做委托或者代理。

做法举例:B中持有C对象引用,A如果想访问C中的方法,一种不使用委托的方法是:A获得B对象,在获得C对象,在调用C中的方法;使用委托的方法是:将C中A要调用的方法,在B对象添加一层代理,这层代理执行通过C对象引用调C的方法,然后A对象可以直接调用这个代理方法。

6、干掉代理

做法是5中做法的逆过程,什么时候干掉代理:还是上面的类A、类B和类C,如果A类和C类的联系太多,每在C内中添加一个新方法,A要使用,则B类就要添加这个代理方法,这样代理会“痛苦不已”,于是干掉代理,A直接调C。

7、引入外加方法

你需要为提供服务的类增加一两个方法,但是你无法修改这个类。(这种情形很常见,比如我调用别的组的代码,我显然不能直接改,最理想方案可以和那个组沟通让对方加,如若不成,求人不如求己,自己也可以解决这个问题)

做法很简单,就是在调用者所在类中,添加一个新的方法。

8、引入本地扩展

你需要为提供服务的类增加一批方法,但是你无法修改这个类。

两种方案:子类化,创建子类对象并新增方法;包装,包装对象持有原对象的引用,创建包装类并新增方法。

子类化和包装两种方案的选择:


首选子类化,

因为工作量较少。子类化方案,直接添加新方法,原有的方法无需改动,直接继承得到;包装方案需要对原来的方法做一层包装,在添加新方法,工作量多。一般来说,不在子类化中覆写原始函数,只添加新函数。

只能选包装方案的情况:因为子类化的方案产生了一个新的子类对象,如果有其他对象引用了旧的对象,那就有两个对象同时保存了原数据,如果原数据不可修改,那没问题,如果原数据允许修改,因为一个修改动作无法同时改变两处,就会存在数据不一致的风险,此时必须使用包装类,因为包装类内部引用的正是原数据,所有只有一份数据。需要注意的是:使用包装类在对有一些方法的处理时比如equal、compare,需要同时照顾到包装类和原始类。



版权声明:本文为qq_39175089原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。