《重构》读书笔记(十一)——第十一章 处理概括关系

第十一章 处理概括关系

     有一批重构手法专门用于处理类的概括关系(generalization,即继承关系),其中主要是将函数上下移动于继承体系之中。

1、上移字段(Pull Up Field)

        判断若干字段是否重复,唯一的办法就是观察函数如何使用它们。如果它们被函数使用的方式很相似,你就可以将它们归纳到超类去。本项重构从两方面减少重复:首先它去除了重复的数据声明;其次它使你可以将使用该字段的行为从子类移至超类,从而去除重复的行为。 

2、上移函数(Pull Up Method)

        避免重复是很重要的!重复只会成为错误的滋生地。无论何时,只要系统之内出现重复,你就会面临“修改其中一处却未能修改另一个”的风险。上移函数(Pull Up Method)是一项很自然的重构。

3、构造函数本体上移(Pull Up Constructor Body)

      本项重构手法用于去掉构造函数中的重复代码。

4、下移函数(Pull Down Method)

        如果超类(基类)中的某个函数只与部分子类有关,那么我们应该将该函数从超类(基类)中下移至特定的子类中(即需要这个特性的子类)。当然,如果你想通过基类对象访问该函数,为了顺利进行,你需要在超类(基类)中将该函数声明为虚函数(virtual),并提供一个默认的实现(或空实现,但不能为纯虚函数)。

5、下移字段(Pull Down Field)

       如果超类(基类)中的某个字段只被部分子类用到,那么就应该将这个字段移至哪些需要这个字段的子类中去。

6、提炼子类(Extract Subclass)

        如果类中的某些特性只被某些实例用到,这是需要“提炼子类”信号。新建一个类,将上面所说的那一部分特性移到子类中。

        Extract Class 和 Extract Subclass 其实就是“委托”和“继承”的抉择。如果一个类承担了超过一个职责,则应该使用提炼类(Extract Class),将其中的部分责任委托给新提炼的类去完成。如果一个类的有些实例用不到它的所有特性,则应该提炼出一个子类(Extract Subclass),并将这部分特性搬移到新提炼的子类中去。

7、提炼超类(Extract Superclass)

       提炼超(基)类。如果两个类有相似特性,那么应该将这些相似的特性提炼到一个基类中。 重复代码是系统中最糟糕的东西!如果你在不同地方做同一件事情,一旦需要修改那些动作,你就得平白做更多的修改。

8、提炼接口(Extract Interface)

       C++多重继承的替代方案。

9、折叠(合并)继承体系(Collapse Hierarchy)

        重构不仅会建立继承体系,也可能会折叠(去除)继承体系。如果我们发现在一个继承体系中,某个子类并未带来该有的价值,我们应该果断移除它。

10、塑造模板函数(Form Template Method)

        塑造模板函数其实就是“定义好处理某种事情的具体步骤(或算法的骨架)”,尽管这些具体步骤的细节可能不同,但这些不同可以通过多态来实现。

11、以委托取代继承(Replace Inheritance With Delegation)

       我们经常纠结于是使用“继承”还是使用“委托”?通常,如果某个子类只使用超类接口中的一部分,或者根本不需要继承而来的数据,这种情况使用委托会更合适。

       很多时候,你一开始继承了一个类,随后你发现基类中的许多操作并不是真正适用于子类。这种情况下,你所拥有的接口并未真正反映出子类的功能。

       你可以选择容忍,因为这种情况通常并不会影响你实现功能。但是,这样的代码所传达的信息与你的意图南辕北撤-----这是一种混淆,我们应该将其去除。

       如果以委托取代继承,你可以更清楚的表明你的意图:你只需要受托类的一部分功能。接口中的哪一部分应该被使用,哪一部分应该被忽略,完全由你主导控制。当然,这样做也是有成本的,即你需要额外的编写出委托函数,但这通常不是问题,因为编写这样的委托函数极其简单。

12、以继承取代委托(Replace Delegation With Inheritance)

      面向对象程序设计中有一条很经典的原则是:优先使用委托而不是继承。这是因为继承往往意味着紧耦合,而委托通常能带来松耦合的系统。但是,有时你也会因为过度信任委托而出错。例如,如果你发现自已需要使用委托类的所有函数,并且费了很大力气编写所有极简的委托函数,那么你应该实施本项重构。

       当然,我们说过:优先使用委托而不是继承。所以,在使用本项重构之前,有两条告诫需要牢记于心:

       首先,如果你并没有使用受托类的所有函数,那么就不要实施本项重构,因为子类应该总是遵循基类的接口(里氏替换原则)。就算过多的委托函数让你烦心,你仍然有别的选择,还记得“移除中间人(Remove Middle Man)”那项重构吗?你可以直接返回受托对象给客户端,让客户代码自己去调用需要的函数,从而可以免除你编写众多委托函数的麻烦。

       其次,如果受托对象被不止一个其他对象共享,而且受托对象是可变的。那么此时你也应该停止本项重构。数据共享是必须由委托关系承担的一种责任,你无法把它转给继承关系。当然,如果仅仅只是数据共享,而数据对象是不可变的,那么我们可以复制对象达到数据共享的目的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值