1. 函数上移
重复的代码是滋生bug的温床,因为很容易修改一个而忘了修改另一个。当多个子类都有功能类似的函数时,则将这个函数总结,提升到父类中。如果该函数还引用了子类中的其他方法和字段,把它们都上移到父类中。其他本没有这个函数的子类可以实现缺省方法,或者抛出异常。
4. 函数下移
如果一个父类中的方法只与少数几个子类相关,则下移到这几个子类中。
3. 构造函数本体上移
将子类中公共语句或公共字段上移到父类中,在子类的构造函数中先调用父类的构造函数。但是要注意,有些公共语句的运行是需要前提的,比如,前提是给一个子类中的字段赋值,而父类中没有这个字段,那么这个公共语句就不该上移。
2. 字段上移
如果子类中有几个字段名字类似,函数使用它们的方式也相同,则将它们合并成一个字段,上移到父类中。
5. 字段下移
如果一个父类中的字段只与少数几个子类相关,则下移到这几个子类中。
6. 以子类取代类型码
其实就是state/strategy模式(相同的类图),一般类型码(比如枚举值)是够用的,但是当多个函数都会根据类型码采取不同的行为,则用子类取代类型码更有效(state模式)。此外,还有些字段或函数只对特定的类型码取值才有意义,也需要采用子类取代类型码。
7. 移除子类
当子类的用处很小,就替换成父类中的一个字段或一个函数。
8. 提取超类
真实世界的分类结构可以作为设计继承关系的提示,但有时候,合理的继承关系是在程序演化的过程中浮现的。当看见两个类在做相似的事,则将相同的字段和函数提取成超类。
9. 折叠继承体系
有时发现一个类与其父类没有多大差别,那就将两个类合并。
10. 以委托取代子类
当一个对象的行为有明显的类别之分,继承是很自然的表示方式,但是在java或是c#中只能有一层继承关系。当物体有多个方向的演化,则善用组合的方式。
还有当继承给类之间引入了非常紧密的关系,当在超类上做任何修改会破坏子类时,采用组合(委托)。(其实就是桥模式)
还有当需要将父类切换成子类时,不方便切换,也可以考虑将子类作为父类的一个字段,将继承关系转为组合关系。
11. 以委托取代超类
如果超类的一些函数对子类并不使用,那么将父类作为子类的一个字段。
合理的继承关系有一个重要特征,就是里氏替换原则,任何使用子类的地方可以使用父类。子类与父类的关系是is a的关系。
还有10 中说的,当在超类上做任何修改会破坏子类时,采用组合(委托)。