Fork me on GitHub

重构手法之重新组织数据【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;
    }
}

12Replace Type Code with State/Strategy(以State/Strategy取代类型码)

posted @ 2019-05-20 20:41  NaYoung  阅读(325)  评论(0编辑  收藏  举报