Summary: 你的各个子类的惟一差异只在“返回常量数据”的函数身上。修改这些函数,使它们返回超类中的某个(新增)字段,而后销毁子类。 java
Motivation: 创建子类的目的,是为了增长新特性或变化其行为。有一种变化行为被称为“常量函数”(constant method),它们会返回一个硬编码的值。这东西有其用途:你可让不一样的子类中的同一个访问函数返回不一样的值。你能够在超类中将访问函数声明为抽象函数,并在不一样的子类中让它返回不一样的值。函数
尽管常量函数有其用途,但若子类中只有常量函数,实在没有足够的存在价值。你能够在超类中设计一个与常量函数返回值相应的子弹,从而彻底去除这样的子类。如此一来就能够避免因继承而带来的额外复杂性。测试
Mechanics:编码
1. 对全部子类使用Replace Constructor with Factory Method.spa
2. 若是有任何代码直接引用子类,令它改而引用超类。设计
3. 针对每一个常量函数,在超类中声明一个final字段code
4.为超类声明一个protected构造函数,用以初始化这些新增字段。对象
5. 新建或修改子类构造函数,使它调用超类的新增构造函数。继承
6.编译,测试。get
7.在超类中实现全部常量函数,令它们返回相应字段值,而后将该函数从子类中删掉
8.没删除一个常量函数,编译并测试。
9.子类中全部的常量函数都被删除后,使用Inline Method将子类构造函数内联到超类的工厂函数中。
10.编译,测试。
11. 将子类删掉。
12. 编译,测试
13. 重复“内联构造函数、删除子类”过程,知道全部子类都被删除。
范例:
本例之中,咱们以Person表示“人”,并针对每种性别创建一个子类:以Male子类表示“男人”,以Female子类表示“女人”:
abstract class Person{ abstract boolean isMale(); abstract char getCode(); ... class Male extends Person{ boolean isMale(){ return true; } char getCode(){ return "M"; } } class Female extends Person{ boolean isMale(){ return false; } char getCode(){ return "F"; } } }
在这里,两个子类之间惟一的区别就是:它们以不一样的方式实现了Person所声明的抽象函数getCode(),返回不一样的硬编码常量(因此getCode()是个长啦ing函数)。咱们应该将这两个子类去掉。
首先须要使用Replace Constructor with Factory Method。在这里,咱们须要为每一个子类创建一个工厂函数:
class Person... static Person createMale(){ return new Male(); } static Person createFemal(){ return new Female(); }
而后把对象建立过程从如下这样:
Person kent = new Male();
改成这样:
Person kent = Person.createMale();
将全部调用构造函数的地方都修改成调用工厂函数以后,就不该该再有任何对子类的直接引用了。一次全文搜索就能够帮助咱们证明这一点。而后,咱们能够把这两个子类都声明为private,这样编译器就能够帮助咱们,保证至少包外不会有任何代码使用它们。
如今,针对每一个常量函数,在超类中声明一个对应的字段:
class Person ... private final boolean _isMale; private fianl char _code;
而后为超类加上一个protected构造函数:
class Person ... protected Person(boolean isMale, char code){ _isMale = isMale; _code = code; }
再为子类加上新构造函数,令它调用超类新增的构造函数:
class Male ... Male(){ super(true, 'M'); } class Female ... Female(){ supre(false, 'F'); }
完成这一步后,编译并测试。全部字段都被建立出来并被赋予初值,但到目前为止,咱们尚未使用它们。如今咱们能够在超类中加入访问这些字段的函数,并删掉子类中的常量函数,从而让这些字段登场:
class Person ... boolean isMale(){ return _isMale; }
咱们能够逐一对每一个字段、每一个子类进行这一步骤的的修改,也能够采起一次性所有修改的手段。
全部字段都处理完毕后,全部子类也都空空如也了,因而能够删除Person中那个抽象函数的abstract修饰符,并以Inline Method将子类构造函数内联到超类的工厂函数中:
calss Pserson ... static Person createMale(){ return new Person(true, 'M'); }
编译,测试后,就能够删掉Male类,并对Female类重复上述过程。