public int PayAmount(EmployeeType empType)
{
switch (empType)
{
case EmployeeType.ENGINEER:
return m_basicSalary;
case EmployeeType.SALESMAN:
return m_basicSalary + m_commission;
case EmployeeType.MANAGER:
return 2 * m_basicSalary;
default:
throw new Exception("no such employee type!");
}
}
现在我们设法将冗余的switch-case语句提炼出来,以期将来需求变化时只需做一次修改即可。
Solution1 使用简单工厂模式:
public abstract class Employee
{
protected int basicSalary;
protected int commission;
public static Employee GetEmployee(EmployeeType empType)
{
switch (empType)
{
case EmployeeType.ENGINEER:
return new Engineer();
case EmployeeType.SALESMAN:
return new SalesMan();
case EmployeeType.MANAGER:
return new Manager();
default:
throw new Exception("no such employee type!");
}
}
public abstract int PayAmount();
public abstract string GetDescription();
}
public class Engineer : Employee
{
public override int PayAmount()
{
return basicSalary;
}
public override string GetDescription()
{
return "Coding, Debug, Optimization";
}
}
public class SalesMan : Employee
{
public override int PayAmount()
{
return basicSalary + commission;
}
public override string GetDescription()
{
return "Getting contracts";
}
}
public class Manager : Employee
{
public override int PayAmount()
{
return 2 * basicSalary;
}
public override string GetDescription()
{
return " Analysis, Scheduling, Reporting ";
}
}
Employee emp = Employee.GetEmployee(EmployeeType.ENGINEER);
Console.WriteLine(emp.GetDescription());
Console.WriteLine(emp.PayAmount());
如果一个Employee对象的EmployeeType是可变的(比如一个engineer升职成了manager),那么简单工厂就不适用了。
这种情况下我们可以使用State模式来解决问题,主要做法就是将EmployeType相关的逻辑提炼出来作为独立的一族类,而Employee类将EmployeeType的实例作为自己的一个property,这样,每个Employee的employee type就成为可变的了:
增加一个EmployeeTypeManager类,这个类专门用于描述和EmployeeType相关的行为。
public abstract class EmployeeTypeManager
{
public int basicSalary;
public int commission;
public abstract int PayAmount();
public abstract string GetDescription();
}
我们把Employee子类中和EmployeeType 相关的方法提取到EmployeeTypeManager类的子类中去。省事的做法是直接将之前的Engineer,SalesMan和Manager类声明成EmployeeType的子类 :P
这里,因为这些类只包含一些和EmployeeType相关的行为,而没有自己的状态,所以我们使用了Singleton的实现。此处仅以Engineer类为例说明:
public class Engineer : EmployeeTypeManager
{
private Engineer() { }
private static Engineer m_Instance;
public static Engineer Instance
{
get
{
if (m_Instance == null)
m_Instance = new Engineer();
return m_Instance;
}
}
public override int PayAmount()
{
return basicSalary;
}
public override string GetDescription()
{
return "Coding, Debug, Optimization";
}
}
private EmployeeTypeManager m_TypeManager;
public EmployeeType EmpType
{
get { return m_type; }
set { m_type = value; }
}
public EmployeeType EmpType
{
get { return m_type; }
set
{
m_type = value;
switch (m_type)
{
case EmployeeType.ENGINEER:
m_TypeManager = Engineer.Instance;
break;
case EmployeeType.SALESMAN:
m_TypeManager = SalesMan.Instance;
break;
case EmployeeType.MANAGER:
m_TypeManager = Manager.Instance;
break;
default:
throw new Exception("no such employee type!");
}
}
}
最后将对Employee类的两个成员方法的调用委托给EmployeeTypeManager:
public int PayAmount()
{
return m_TypeManager.PayAmount();
}
public string GetDescription()
{
return m_TypeManager.GetDescription();
}
Employee类内置的EmployeeTypeManager对象将随着其EmployeeType的改变而改变,从而同一个Employee对象也随之有了不同的行为。
整个过程将各个case的实现逻辑从Employee的子类移到了EmployeeTypeManager及其子类中去,相应的,switch - case判断也被从Employee的简单工厂中移动到了property里。