您的位置:首页 > 其它

Replace Subclass with Fields(以值域取代子类)

2009-02-12 16:02 316 查看
你的各个class的唯一差别只在[返回常量数据]的函数身上。

修改这些函数,使它们返回superclass中的某个(新增)值域,然后销毁subclasses。



动机

建立subclass的目的,是为了增加新特性或变化其行为。有一种变化行为称为常量函数,它们会返回硬编码值。这东西有其用途,你可以对不同的subclass中的同一个访问函数返回不同的值,你可以在superclass中将访问函数声明为抽象函数,并在不同的subclass中让它返回不同的值。

虽然常量函数有其用途,但若subclass中只有常量函数,实在没有足够的存在价值,你可以在super class中设计一个与常量函数返回值相应的值域,从而去除这样的subclass,如此一来就可以避免subclassing而带来的额外复杂性。

作法

1. 对所有subclasses使用Replace Constructor with Factory Method

2. 如果有任何代码直接引用subclass,令它改而引用superclass

3. 针对每个常量函数,在superclass中声明一个final值域

4. 为superclass声明一个protected构造函数,用以初始化这些新增值域

5. 新建或修改subclass构造函数,使它调用superclass的新增构造函数

6. 编译、测试

7. 在superclass中实现所有常量函数,令它们返回相应值域值,然后将该函数从subclass中删除

8. 每删除一个常量函数,编译并测试

9. subclass中所有的常量函数都被删除后,使用Inline Method将subclass的构造函数内联到superclass的factory method中

10. 编译、测试

11. 将subclass删除

12. 编译、测试

13. 重复[构造函数内联,删除subclass]过程,直到所有subclasses都被删除。

我以一个以性别为区分各个子类的例子:

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';
}
}

在这里,两个subclasses之间唯一的区别就是,它们以不同的方式实现了Person所声明的抽象函数,返回硬编码的值,我要去掉这样的子类

首先,我需要使用Replace Constructor with Factory Method。在这里,我需要为每个subclass建立一个factory Method。

class Person...
static Person createMale(){
return new Male();
}
static Person createFemale() {
return new Female();
}

然后,我把对象创建过程从以下这样

Person kent = new Male();

改为

Person kent = Person.createMale();

将所有构造函数都改为factory Method后,我就不应该再有任何对subclass的直接引用了。一次全文搜索就可以帮我证实这一点,然后,我可以把这两个subclass都声明为private,这样编译器可以帮助我,至少package之外不会有任何代码取用它们。

现在,针对每个常量函数,在superclass中声明一个对应的值域:

class Person...
private final boolean _isMale;
private final char _code;

然后为superclass加入一个protected构造函数

class Person...
protected Person (boolean isMale, char code) {
_isMale = isMale;
_code = code;
}

再为subclass加入新构造函数,令它调用superclass新增的构造函数

class Male...
Male() {
super (true, 'M');
}
class Female...
Female() {
super (false, 'F');
}

完成这一步后,编译并测试,所有值域都被创建出来并被赋予初值,但到目前我们还没有使用它们。现在我可以在superclass中加入访问这些值域的函数,并删除subclass中的常量函数,从而让这些值域粉墨登场。

class Person...
boolean isMale() {
return _isMale;
}
class Male...
boolean isMale() {
return true;
}

我们可以逐一对每个值域、每个subclass进行这一步骤的修改。如果我相信自己的运气,也可以采取一次性全部修改的手段。所有值域都处理完毕后,所有subclasses都空空如也了。于是我可以删除Person中那个抽象函数的abstract修饰符,并以Inline Method将subclass构造函数内联到superclass中的factory method中。

class Person
static Person createMale(){
return new Person(true, 'M');
}

编译测试后,我就可以删掉Male Class,并对Female Class重复上述过程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: