重构手法之重新组织数据【4】
返回总目录
10Replace Type Code with Class(以类取代类型码)
概要
类之中有一个数值类型码,但它不影响类的行为。以一个新的类替换该数值类型码。
动机
在以C为基础的编程语言中,类型码或枚举值很常见。如果带着一个有意义的符号名,类型码的可读性还不错。问题在于,符号名终究只是个别名,编译器看见的、进行类型检验的,还是背后那个数值。任何接受类型码作为参数的函数,所期望的实际上是一个数值,无法强制使用符号名。这会大大降低代码的可读性,从而成为bug之源。
如果把那样的数值换成一个类,编译器就可以对这个类进行类型检验。只要为这个类提供工厂函数,你就可以始终保证只有合法的实例才会被创建出来,而且他们都会被传递给正确的宿主对象。
范例
每个人都拥有四种血型中的一种。我们以Person来代表“人”,以其中的类型码表示“血型”:
class Person { public static int O = 0; public static int A = 1; public static int B = 2; public static int AB = 3; public int BloodGroup { get; set; } public Person(int bloodGroup) { BloodGroup = bloodGroup; } }
重构后代码如下:
public class Person { public BloodGroup BloodGroup { get; set; } public Person(BloodGroup bloodGroup) { BloodGroup = bloodGroup; } } public class BloodGroup { public static readonly BloodGroup O = new BloodGroup(0); public static readonly BloodGroup A = new BloodGroup(1); public static readonly BloodGroup B = new BloodGroup(2); public static readonly BloodGroup AB = new BloodGroup(3); public int Code { get; } public BloodGroup(int bloodGroup) { Code = bloodGroup; } }
11Replace Type Code with Subclasses(以子类取代类型码)
概要
你有一个不可变的类型码,它会影响类的行为。以子类取代这个类型码。
动机
如果你面对的类型码不会影响宿主类的行为,可以使用Replace Type Code with Class来处理它们。但如果类型码会影响宿主类的行为,那么最好的办法就是借助多态来处理变化行为。
一般来说,这种情况的标志就是像switch这样的条件表达式。这种条件表达式可能有2种表现形式:switch语句或者if–then-else结构。不论哪种形式,它们都是检查类型码值,并根据不同的值执行不同的动作。这种情况下,应该以Replace Conditional with Polymorphism进行重构。但为了能够顺利进行那样的重构,首先应该将类型码替换为可拥有多态行为的继承体系。这样一个继承体系应该以类型码宿主类为基类,并针对每一种类型码建立一个子类。
为建立这样的继承体系,最简单的办法就是使用本重构:以类型码的宿主类为基类,针对每种类型码建立相应的子类。
范例
有一个简单的雇员类:
class Employee { public static int ENGINEER = 0; public static int SALESMAN = 1; public static int MANAGER = 2; public int Type { get; } public Employee(int type) { Type = type; } }