重构(十)重构名录-处理继承关系
2019-05-15 本文已影响0人
天色将变
函数上移Pull Up Method
image.png- 提取公共方法到超类
字段上移Pull Up Field
image.png- 提起公共字段到超类
构造函数本体上移 Pull Up Constructor Body
image.png- 提取公共构造函数到超类
函数下移Push Down Method
image.png- 特性函数放到子类
字段下移 Push Down Field
image.png- 特性字段放到子类
以子类取代类型码Replace Type Code with Subclasses
image.png- 动机:软件系统经常需要表现“相似但又不同的东西”。表现分类关系的第一种工具是类型码字段——根据具体的编程语言,可能实现为枚举/符号/字符串或者数字。大多数时候,这样的类型码句够用了。但有些时候,可以再往前一步,引入子类。可以用多态来处理条件逻辑,如果有几个函数都在根据类型码的取值采取不同的行为,多态就显得特别有用。以多态取代条件表达式。
移除子类Remove Subclass
image.png- 动机:子类很有用,它们为数据结构的多样和行为的多态提供支持,它们是针对差异编程的好工具。子类存在着就有成本,阅读者要花心思去理解它的用意,所以如果子类的用处太少,就不值得存在了。
提炼超类 Extract Superclass
image.pngimage.png
- 动机:如果我看见两个类在做相似的事,可以利用基本的继承机制把它们的相似之处提炼到超类。
折叠继承体系 Collapse Hierarchy
image.png- 动机:在重构类继承体系时,我经常把函数和字段上下移动。随着继承体系的演化,我有时会发现一个类与其超类已经没多大差别,不值得再作为独立的类存在。此时我就会把超类和子类合并起来。
以委托取代子类 Replace Subclass with Delegate
image.png- 动机:如果一个对象的行为有明显的类别之分,继承是很自然的表达方式。我可以把共用的数据和行为放在超类中,每个子类根据需要覆写部分特性。在面向对象语言中,继承很容易实现。
- 继承的短板:
- 只能用于处理一个方向上的变化。
- 继承给类之间引入了非常紧密的关系。在超类上做任何修改,都很可能破坏子类,所以必须非常小心,并且充分理解子类如何从超类派生。如果两个类的逻辑分处不同的模块,由不同的团队负责,问题更麻烦。
- 这两个问题可以用委托解决。对于不同变化的原因,委托给不同的类。委托是对象之间常规的关系。与继承关系相比,使用委托关系时接口更清晰耦合更少。因此,继承关系遇到问题时可以运用委托取代子类。
以委托取代超类 Replace Superclass with Delegate
image.png- 合理使用继承体系。超类A的所有字段方法都会出现在子类上,子类B必须全盘接受,否则就不能使用继承。B继承A的目的是想借用A的部分字段方法,继承不合适的话,可以使用委托,让A成为B的一个字段,让B想要的操作委托给A来实现。
- 也就是说不能形成继承体系,但又想复用,可以使用委托。