类替换类型码 和 子类替换类型码 都是重构手法,旨在替换代码中使用的类型码,但是它们的适用场景和处理方式有一些区别:
1. 适用场景的不同
-
类替换类型码:
- 适用于类型码主要携带数据,并可能伴随一些行为的场景。
- 类型码的主要功能是标识或区分数据的不同类别,并且这些类别可能具有某些相同的基本行为,但处理方式稍有不同。
- 通常用来为每个类型码创建一个单一的类,将其封装为对象,并且这些对象可能是平行的,并不会继承自同一个基类。
示例:将
Money
类型替换为类,类型码可能是货币种类(美元、欧元等),但它们可以封装在不同的Currency
类中,而不是通过子类继承来表现不同行为。 -
子类替换类型码:
- 适用于类型码控制不同对象行为的场景,不同类型的行为存在显著差异。
- 类型码不仅用于标识类型,还决定了对象的行为逻辑,因此使用子类可以利用多态来实现不同的行为。
- 通常用来通过继承来将类型码替换为子类,每个子类有自己独特的行为或方法实现。
示例:员工类型(全职、兼职)用类型码区分,且这两种类型的员工有完全不同的奖金计算方式或其他业务逻辑,可以通过子类来实现这种行为的分离。
2. 重构目标的不同
-
类替换类型码:
- 目标是将类型码封装为一个类,这个类包含数据和一些与之相关的操作。
- 它强调的是将数据与行为结合,形成单一职责的类,而不是复杂的继承体系。
- 这个类主要封装的是数据的操作,并不一定具有复杂的多态性。
-
子类替换类型码:
- 目标是通过继承来消除类型码,通过子类的多态性实现不同的行为。
- 它更注重行为差异的表达,不同子类分别实现特定的逻辑。
- 强调的是通过继承和多态来简化
if-else
或switch-case
的逻辑。
3. 实现方式的不同
-
类替换类型码:
- 我们会为每个类型创建一个类,通常这些类之间没有继承关系,它们平行地处理不同的数据。
- 主要将类型码替换为类的实例,进而移植与该类型相关的行为到类内部。
-
子类替换类型码:
- 我们会为类型码的不同值创建子类,让这些子类继承自同一个父类或抽象类。
- 每个子类会根据其类型的不同实现自己的行为,利用多态特性替代类型码的判断。
示例对比
类替换类型码
假设我们有一个简单的货币类型码:
public class Transaction
{public int CurrencyType { get; set; } // 1 for USD, 2 for EURpublic decimal ConvertToBaseCurrency(decimal amount){if (CurrencyType == 1) // USD{return amount * 1.0m;}else if (CurrencyType == 2) // EUR{return amount * 1.1m;}else{throw new ArgumentException("Invalid currency type.");}}
}
优化为类:
public class Currency
{public virtual decimal ConvertToBaseCurrency(decimal amount) => amount;
}public class USD : Currency
{public override decimal ConvertToBaseCurrency(decimal amount) => amount * 1.0m;
}public class EUR : Currency
{public override decimal ConvertToBaseCurrency(decimal amount) => amount * 1.1m;
}
每个货币类型成为一个独立的类,但它们没有继承关系,逻辑相对简单。
子类替换类型码
假设我们有一个 Employee
类,使用类型码来处理全职与兼职员工的奖金:
public class Employee
{public int EmployeeType { get; set; } // 1 for Full-time, 2 for Part-timepublic decimal GetBonus(){if (EmployeeType == 1) // Full-time{return 1000;}else if (EmployeeType == 2) // Part-time{return 500;}else{throw new ArgumentException("Invalid employee type.");}}
}
优化为子类:
public abstract class Employee
{public abstract decimal GetBonus();
}public class FullTimeEmployee : Employee
{public override decimal GetBonus(){return 1000;}
}public class PartTimeEmployee : Employee
{public override decimal GetBonus(){return 500;}
}
这里我们用子类来替代类型码,不同类型的员工有不同的行为实现,利用了继承和多态性。
总结
- 类替换类型码 更适合用于类型码主要携带数据的情况,且这些类型没有显著的行为差异。
- 子类替换类型码 更适合用于类型码主导对象行为的场景,且不同类型的行为差异较大,可以通过继承和多态来简化代码逻辑。
这两种重构方式的选择主要取决于类型码的作用是更多地承载数据,还是决定对象的行为。