Case如下,假設(shè)Employee類(lèi)中有這樣兩個(gè)方法:
PayAmount. 根據(jù)員工類(lèi)型獲得員工的薪水:
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!");
}
}
GetDescription. 根據(jù)員工類(lèi)型獲得職責(zé)描述:
public string GetDescription(EmployeeType empType)
 {
switch (empType)
 {
case EmployeeType.ENGINEER:
return "Coding, Debug, Optimization";
case EmployeeType.SALESMAN:
return "Getting contracts";
case EmployeeType.MANAGER:
return "Analysis, Scheduling, Reporting";
default:
throw new Exception("no such employee type!");
}
}
這兩個(gè)方法含有兩個(gè)幾乎一模一樣的switch-case語(yǔ)句,如果將來(lái)需要增加一種情況,比如“Senior Engineer”那么我們需要去找到這2個(gè)方法并分別修改他們。假如一個(gè)龐大的系統(tǒng)中有很多這樣的方法,改起來(lái)就會(huì)很麻煩。
現(xiàn)在我們?cè)O(shè)法將冗余的switch-case語(yǔ)句提煉出來(lái),以期將來(lái)需求變化時(shí)只需做一次修改即可。
Solution1 使用簡(jiǎn)單工廠模式:
為Employee類(lèi)構(gòu)造一個(gè)簡(jiǎn)單工廠,能夠根據(jù)不同的EmployeeType返回相應(yīng)的子類(lèi)實(shí)例。
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();
}
為switch - case 語(yǔ)句中的不同case分別創(chuàng)建子類(lèi),接著將不同case下的邏輯提煉成方法裝入相應(yīng)的子類(lèi):
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 ";
}
}
至此,EmployeeType參數(shù)就可以從兩個(gè)方法中移除了,我們只需在構(gòu)造Employee對(duì)象時(shí)指定一次EmployeeType,就能獲得想要的Employee行為:
Employee emp = Employee.GetEmployee(EmployeeType.ENGINEER);
Console.WriteLine(emp.GetDescription());
Console.WriteLine(emp.PayAmount());

Solution2 使用State模式:
如果一個(gè)Employee對(duì)象的EmployeeType是可變的(比如一個(gè)engineer升職成了manager),那么簡(jiǎn)單工廠就不適用了。 這種情況下我們可以使用State模式來(lái)解決問(wèn)題,主要做法就是將EmployeType相關(guān)的邏輯提煉出來(lái)作為獨(dú)立的一族類(lèi),而Employee類(lèi)將EmployeeType的實(shí)例作為自己的一個(gè)property,這樣,每個(gè)Employee的employee type就成為可變的了:
增加一個(gè)EmployeeTypeManager類(lèi),這個(gè)類(lèi)專(zhuān)門(mén)用于描述和EmployeeType相關(guān)的行為。
public abstract class EmployeeTypeManager
 {
public int basicSalary;
public int commission;
public abstract int PayAmount();
public abstract string GetDescription();
}

我們把Employee子類(lèi)中和EmployeeType 相關(guān)的方法提取到EmployeeTypeManager類(lèi)的子類(lèi)中去。省事的做法是直接將之前的Engineer,SalesMan和Manager類(lèi)聲明成EmployeeType的子類(lèi) :P
這里,因?yàn)檫@些類(lèi)只包含一些和EmployeeType相關(guān)的行為,而沒(méi)有自己的狀態(tài),所以我們使用了Singleton的實(shí)現(xiàn)。此處僅以Engineer類(lèi)為例說(shuō)明:
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";
}
}
接著在Employee類(lèi)中聲明一個(gè)EmployeeTypeManager類(lèi)型的私有成員并為EmployeeType暴露一個(gè)property供外界修改:
private EmployeeTypeManager m_TypeManager;
public EmployeeType EmpType
 {
 get { return m_type; }
 set { m_type = value; }
}

將switch-case邏輯從原先的簡(jiǎn)單工廠挪到EmployeeType的set方法中去:
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!");
}
}
}
最后將對(duì)Employee類(lèi)的兩個(gè)成員方法的調(diào)用委托給EmployeeTypeManager:
public int PayAmount()
 {
return m_TypeManager.PayAmount();
}
public string GetDescription()
 {
return m_TypeManager.GetDescription();
}
Employee類(lèi)內(nèi)置的EmployeeTypeManager對(duì)象將隨著其EmployeeType的改變而改變,從而同一個(gè)Employee對(duì)象也隨之有了不同的行為。
整個(gè)過(guò)程將各個(gè)case的實(shí)現(xiàn)邏輯從Employee的子類(lèi)移到了EmployeeTypeManager及其子類(lèi)中去,相應(yīng)的,switch - case判斷也被從Employee的簡(jiǎn)單工廠中移動(dòng)到了property里。
|