重构心法修炼第五层:处理概括关系
11.1 字段上移
两个子类拥有相同的字段,将该字段移动到超类。
本重构优势在于:去除重复声明,并去除重复行为。
11.2 函数上移
有些函数,在各个子类中产生完全相同的效果。若函数签名不同, 修改函数签名到一致并上移至超类。
如果要被向上抽取的函数调用了子类的其它函数,可以一并将该函数移动到超类,或者直接在超类中声明一个抽象函数。
11.3 构造函数上移
如果各个子类的构造函数中有相同的SET函数,可以在超类中提供一个构造函数。
如果各个子类的构造函数中有相同的行为,那么可以在超类中定义一个initalize()方法。子类构造函数中执行initalize()方法。如果这个方法中的方法体依赖到的子类的其它函数,那么可以在超类中定义相关的抽象方法。
class Employee ...
void initialize( ){ if( isVip() ) { asignCar() } } //父类拥有抽象方法
class Manager extends Employee ...
public Manager(){ super(); initalize() ; }
boolean isVip();
void asignCar();
11.4 字段或函数下移
超类中的某个字段或者某个函数只与特定子类有关,将其搬移到特定子类中。
11.6 提炼子类
超类中的某些特性只被某些(而非全部)实例用到,新建一个子类,将上面所说的那一部分特性提炼到子类中。
例如,如果超类提供的收费规则有按时计费与按局数计费,将他们分别抽取为子类,并且将超类声明为抽象的。
1.在子类中建立一个相同的构造函数,并将超类的构造函数改为protected。
2.在子类中创建自己的构造函数,参数数量比超类要少,并用固定的特征值来调用超类构造函数。
3.将关于子类的超类字段修改为protected
4.修改超类构造函数,让超类构造函数摆脱此子类特征字段。在子类构造函数中,将特征字段用this.xxx = xxx;接收
5.找到超类中调用此特性的地方,并在超类与子类中使用多态各建立一份常量函数。
6.从超类中下移子类特性字段。
11.8 提炼接口
如果某个类在不同环境下扮演不同的角色,使用接口就是一个好主意。
两个类有相同接口的时候,将相同的接口提炼到一个独立的接口中。
两个类有相同方法或者相同的接口的时候,可提炼出一个指定功能的接口,并将使用此类的地方改用接口形式。
一个接口代表着一种功能,可以最大化的隐藏该对象的其他功能。如果一个方法使用接口作为方法名,那么此方法可以接收任何实现了接口的类,这样有助于代码的复用性与灵活性。
11.10 塑造模版函数
抽象超类定义流程,子类使用多态保持子类之间的差异性。
11.11 以委托取代继承
如果一个类使用了超类中的部分功能,或者说没必要继承所有的超类功能的时候。在子类中建立一个超类对象,然后委托超类对象来完成功能的实现。
11.12 以继承取代委托
如果委托到了某个类的所有方法,不如直接继承此类。