子类替换类型码 是一种用于将类型码替换为子类。当代码使用类型码(通常是 int
、string
或 enum
)来表示对象的不同类别,并且这些类别的行为有所不同时,使用子类可以更加清晰地表达这些差异并减少复杂的条件判断。
一、什么时候使用
- 当我们发现不同的类型码对应的对象行为有所不同,并且在代码中使用
if-else
或switch-case
语句来处理不同类型的行为。 - 当类型码背后的行为变得越来越复杂,处理逻辑变得难以维护。
- 当每个类型码代表的类别可能拥有不同的属性或方法时。
二、优化步骤
- 识别类型码 :找到那些使用类型码来区分对象行为的地方,通常是用来驱动
if-else
或switch-case
语句。 - 为每个类型创建子类:为每个类型码创建一个对应的子类,从原类继承。
- 将行为移植到子类:把与类型码相关的不同行为从原来的条件语句中提取出来,移动到各个子类中。
- 替换类型码:在对象实例化的地方,使用子类来代替类型码。
三、示例
假设我们有一个 Employee
类,使用类型码 EmployeeType
来表示全职员工和兼职员工,并根据类型码的不同计算奖金:
csharp
public class Employee
{
public int EmployeeType { get; set; } // 1: Full-time, 2: Part-time
public decimal GetBonus()
{
if (EmployeeType == 1)
{
return 1000;
}
else if (EmployeeType == 2)
{
return 500;
}
else
{
throw new ArgumentException("Invalid employee type.");
}
}
}
3.1 优化后的代码
可以为全职和兼职员工创建子类,消除类型码并让每个子类自行实现 GetBonus
方法:
csharp
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;
}
}
在客户端代码中,实例化不同的员工子类:
csharp
Employee fullTimeEmployee = new FullTimeEmployee();
Employee partTimeEmployee = new PartTimeEmployee();
Console.WriteLine(fullTimeEmployee.GetBonus()); // 输出 1000
Console.WriteLine(partTimeEmployee.GetBonus()); // 输出 500
四、优化的好处
- 消除条件判断 :不同类型的行为由各自的子类负责,不再需要通过
if-else
或switch-case
来判断类型,简化了代码结构。 - 增强可扩展性:新增类型时,只需创建新的子类,不需要修改现有的代码,从而遵循了开闭原则(Open/Closed Principle)。
- 集中职责:每个子类专门处理与它相关的行为,职责更加单一,符合单一职责原则(Single Responsibility Principle)。
- 更具可读性和维护性:每个子类的行为清晰且独立,代码更易于理解和维护。
五、适用场景
- 多态场景:当不同类型的对象有不同的行为表现时,使用子类可以充分利用面向对象编程的多态性。
- 复杂条件逻辑:当处理类型码的条件判断过于复杂或冗长时,将类型码替换为子类能够减少这些复杂的条件逻辑。
- 未来类型扩展:如果预期会增加新的类型码,使用子类可以避免频繁修改现有代码。
六、示例扩展
如果不同员工类型除了奖金计算之外还涉及其他不同的业务逻辑,比如工资计算、休假天数等,用子类封装这些行为将使代码更加清晰。每个子类不仅仅是实现不同的 GetBonus
,还可以根据需要扩展其他专属行为。
csharp
public abstract class Employee
{
public abstract decimal GetBonus();
public abstract int GetVacationDays();
}
public class FullTimeEmployee : Employee
{
public override decimal GetBonus()
{
return 1000;
}
public override int GetVacationDays()
{
return 20;
}
}
public class PartTimeEmployee : Employee
{
public override decimal GetBonus()
{
return 500;
}
public override int GetVacationDays()
{
return 10;
}
}
使用子类替代类型码能够让代码结构更加简洁、易维护,并且提升了扩展性。不同类型的对象通过子类来管理各自的行为,充分利用了面向对象编程的多态特性,从而减少复杂的条件判断和潜在错误。