8.13 replace type code with class(以类取代类型码)

类之中有一个数值类型码,但它并不影响类的行为。

以一个新的类替换该数值类型码。

动机:

如果带着一个有意义的符号名,类型码的可读性还是不错的。问题在于,符号名终究只是个别名,编译器看见的,进行类型检验的,还是背后那个数值。任何接受类型码作为参数的函数,所期望的实际上是一个数值,无法强制使用符号名。

如果把那样的数值换成一个类,编译器就可以对这个类进行类型检验。只要为这个类提供工厂函数,你就可以始终保证只有合法的实例才会被创建出来,而且它们会被传递给正确的宿主对象。

只有当类型码是纯粹数据时,你才能以类来取代它。

任何switch语句都应该使用replace conditional with polymorphism去掉。为了进行重构,必须运用replace type code with subclasses或replace type code with state/strategy,把类型码处理掉。

即使一个类型码不会因其数值的不同而引起行为上的差异,宿主类中的某些行为还是有可能更适合置放于类型码类中,因此你还应该留意是否有必要使用move method将一两个函数搬过去。

做法:

为类型码建立一个类。

=》这个类需要一个用于记录类型码的字段,其类型应该和类型码相同,并应该有对应的取值函数。此外还应该用一组静态变量保存允许被创建的实例,并以一个静态函数根据原本的类型码返回合适的实例。

修改源类实现,让它使用上述新建的类。

=》维持原先以类型码为基础的函数接口,但改变静态字段,以新建的类产生代码,然后,修改类型码相关函数,让它们也从新建的类中获取类型码。

对于源类中的每一个使用类型码的函数,相应建立一个函数,让新函数使用新建的类。

=》你需要建立“以新类实例为自变量”的函数,用以替换原先“直接以类型码为参数”的函数。你还需要建立一个“返回新类实例”的函数,用于替换原先“直接放回类型码”的函数。建立新函数前,可以使用rename method修改原函数名称,明确指出哪些函数仍然使用旧式的类型码。

逐一修改源类用户,让它们使用新接口。


旧代码

class Person{
public static final int O = 0;
public static final int A = 1;
public static final int B = 2;
public static final int AB = 3;
private int _bloodGroup;
public Person(int bloodGroup){
    _bloodGroup = bloodGroup;
}
public void setBloodGroup(int arg){
    _bloodGroup = arg;
}
public int getBloodGroup(){
    return _bloodGroup;
}
}


新代码

class BloodGroup{
public static final BloodGroup O = new BloodGroup(0);
public static final BloodGroup A = new BloodGroup(1);
public static final BloodGroup B = new BloodGroup(2);
public static final BloodGroup AB = new BloodGroup(3);
private static final BloodGroup[] _values = {O, A, B, AB};
private final int _code;
private BloodGroup(int code){
    _code = code;
}
public int getCode(){
    return _code;
}
public static BloodGroup code(int arg){
    return _values[arg];
}
}

class Person{
private BloodGroup _bloodGroup;
public int getBloodGroupCode(){
    return _bloodGroup.getCode();
}
public BloodGroup getBloodGroup(){
    return _bloodGroup;
}
public Person(BloodGroup bloodGroup){
    _bloodGroup = bloodGroup;
}
public void setBloodGroup(BloodGroup arg){
    _bloodGroup = arg;
}
}

Person theperson = new Person(BloodGroup.A)
thePerson.setBloodGroup(BloodGroup.AB)







阅读更多
文章标签: class 编译器
上一篇8.2 replace data value with object(以对象取代数据值)
下一篇8.14 replace type code with subclasses (以子类取代类型码)
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭