【重构.改善既有代码的设计】7、在对象之间搬移特性(如何优化类)

7、在对象之间搬移特性

Move Method(搬移函数)

描述:
有个函数与其所驻class之外的另一个class进行更多交流:调用后者,或被后者调用。
在该函数最常引用(指涉)的class中建立一个有着类似行为的新函数。将旧函数变成一个单纯的委托函数(delegating method),或是将旧函数完全移除。

原因:
高耦合。依赖情节。

注意:
1、在迁移的时候,要考虑函数用到的属于原class的变量及其他函数,是否也应该迁移,这会是更大的收获。
2、不是所有变量都需要移动的,不能移动的作为调用参数也是可以的。

Move Field(搬移值域)

描述:
你的程序中,某个field(值域〕被其所驻class之外的另一个class更多地用到。
在target class 建立一个new field,修改source field的所有用户,令它们改用此new field。

Extract Class(提炼类)

某个class做了应该由两个classes做的事。
建立一个新class,将相关的值域和函数从旧class搬移到新class。

原因:
1、单一职责原则,一个变化只应该影响一个类,多种变化应该影响多个类。
2、改善并发,可以缩小锁的范围,精确锁的粒度。

使用场景:1、方法太多,2、变量太多。这样的class往往太大而不易理解。此时你需要考虑哪些部分可以分离出去,并将它们分离到一个单独的class中。

后续:
1、决定这个类要不要对外暴露?如果不暴露,可以采用委托方式。

Inline Class(将类内联化)

你的某个class没有做太多事情(没有承担足够责任)。
将class的所有特性搬移到另一个class中,然后移除原class。

与Extract Class 相反。

Hide Delegate(隐藏「委托关系」)

客户直接调用其server object(服务对象)的delegate class。

在server端(某个class〕建立客户所需的所有函数,用以隐藏委托关系(delegation)。

委托有好有坏,还是要根据情况决定是否要隐藏委托。

Remove Middle Man(移除中间人)

某个class做了过多的简单委托动作(simple delegation)。

让客户直接调用delegate(受托类)。

“Hide Delegate(隐藏「委托关系」)”的逆操作。

Introduce Foreign Method(引入外加函数)

你正在使用一个class,它真的很好,为你提供了你想要的所有服务。
而后,你又需要一项新服务,这个class却无法供应。
于是你开始咒骂:「为什么不能做这件事?」如果可以修改源码,你便可以自行添加一个新函数; 
如果不能,你就得在客户端编码,补足你要的那个函数。

其实就是把外面的方法装饰一下提供一个符合自己要求的新方法。

如果需要多个函数,或者多个类需要这个函数,那就用下一个方法:Introduce Local Extension(引入本地扩展)

Introduce Local Extension(引入本地扩展)

你所使用的server class需要一些额外函数,但你无法修改这个class。

建立一个新class,使它包含这些额外函数。让这个扩展品成为source class的subclass (子类〕或wrapper(外覆类)。

1、使用Subclass(子类)

这个容易的。继承后新加函数就好了。

2、使用wrapper(外覆类)

这种方案是在wrapper类中,聚合一个原始类,然后为原始类所有用到的函数提供委托函数。这个就会很烦。

原作者的总结

在对象的设计过程中,「决定把责任放在哪儿」即使不是最重要的事,也是最重要的事之一。
我使用对象技术已经十多年了,但还是不能一开始就保证做对。
这曾经让我很烦恼,但现在我知道,在这种情况下,我可以运用重构(refactoring),改变自己原先的设计。

常常我可以只运用 Move Method 和Move Field 简单地移动对象行为,就可以解决这些问题。
如果这两个重构手法都需要用到,我会首先使用Move Field,再使用Move Method。

class往往会因为承担过多责任而变得臃肿不堪。这种情况下,我会使用Extract Class 将一部分责任分离出去。
如果一个class变得太「不负责任」,我就会使用Inline Class 将它融入另一个class。
如果一个class使用了另一个class,运用Hide Delegate 将这种关系隐藏起来通常是有帮助的。
有时候隐藏delegate class会导致拥有者的接口经常变化,此时需要使用Remove Middle Man。

本章的最后两项重构——Introduce Foreign Method 和Introduce Local Extension ——比较特殊。
只有当我不能访问某个class的源码,却又想把其他责任移进这个不可修改的class时,我才会使用这两个重构手法。
如果我想加入的只是一或两个函数,我会使用Introduce Foreign Method;如果不止一两个函数,我就使用Introduce Local Extension。

我的总结

相对于第6章讲的是解决长函数的问题,本章讲的是不合理类的优化。

优化手段如下:
1、职责过多: 
1.1、包含了本属于其他类的函数:Move Method(搬移函数)
1.2、包含了本属于其他类的值:Move Field(搬移值域)
1.3、其他类还没有创建:Extract Class(提炼类)
2、职责过少:Inline Class(将类内联化)
3、聚合对象(中间人)接口过多/接口常变,维护困难:Remove Middle Man(移除中间人)
4、聚合对象(中间人)接口简单稳定,但访问多,需隐藏:Hide Delegate(隐藏「委托关系」)
5、少数sdk常用功能的扩展:Introduce Foreign Method(引入外加函数)
6、多数sdk常用功能的扩展:Introduce Local Extension(引入本地扩展)

posted @ 2019-02-15 14:53  傲衣华少  阅读(369)  评论(0编辑  收藏  举报