Replace Type Code with Class 以类取代类型码
类之中有一个数值类型码,但它并不影响类的行为。以一个新的类替换该数值类型码。
动机
在以C为基础的编程语言中,类型码或枚举值很常见。如果带着一个有意义的符号名,类型码的可读性还是不错的。问题在于,符号名终究只是个别名,编译器看见的、进行类型检验的,还是背后那个数值。任何接受类型码作为参数的函数,所期望的实际上是一个数值,无法强制使用符号名。这会大大降低代码的可读性,从而成为bug之源。
如果把那样的数值换成一个类,编译器就可以对这个类进行类型检验。只要为这个类提供工厂函数,你就可以始终保证只有合法的实例才会被创建出来,而且它们都会被传递给正确的宿主对象。
但是,在使用Replace Type Code with Class之前,你应该先考虑类型码的其他替换方式。只有当类型码是纯粹数据时(也就是类型码不会在switch语句中引起行为变化时),你才能以类来取代它。Java只能以整数作为switch语句的判断依据,不能使用任意类,因此那种情况下不能够以类替换类型码。更重要的是:任何switch语句都应该运用Replace Conditional with Polymorphism去掉。为了进行那样的重构,你首先必须运用Replace Type Code with Subclasses或Replace Type Code with State/Strageygy,把类型码处理掉。
即使一个类型码不会因其数值的不同而引起行为上的差异,宿主类中的某些行为还是有可能更适合置放于类型码类中,因此你还应该留意是否有必要使用Move Method将一两个函数搬过去。
做法
- 为类型码建立一个类。
- 这个类需要一个用以记录类型码的字段,其类型应该和类型码相同,并应该有对应的取值函数。此外还应该用一组静态变量保存允许被创建的实例,并以一个静态函数根据原本的类型码返回合适的实例。
- 修改源类实现,让它使用上述新建的类。
- 维持原先以类型码为基础的函数接口,但改变静态字段,以新建的类产生代码。然后,修改类型码相关函数,让它们也从新建的类中获取类型码。
- 编译,测试。
- 此时,新建的类可以对类型码进行运行期检查。
- 对于源类中每一个使用类型码的函数,相应建立一个函数,让新函数使用新建的类。
- 你需要建立“以新类实例为自变量”的函数,用以替换原先“直接以类型码为参数”的函数。你还需要建立一个“返回新类实例”的函数,用以替换原先“直接返回类型码”的函数。建立新函数前,你可以使用Rename Method修改原函数名称,明确指出哪些函数仍然使用旧式的类型码,这往往是个明智之举。
- 逐一修改源类用户,让它们使用新接口。
- 每修改一个用户,编译并测试。
- 你也可能需要一次性修改多个彼此相关的函数,才能保持这些函数之间的一致性,才能顺利地编译、测试。
- 删除使用类型码的旧接口,并删除保存旧类型码的静态变量。
- 编译,测试。