概述
在軟件系統中,經常面臨著“一系列相互依賴的對象”的創建工作;同時由於需求的變化,往往存在著更多系列對象的創建工作。如何應對這種變化?如何繞過常規的對象的創建方法(new),提供一種“封裝機制”來避免客戶程序和這種“多系列具體對象創建工作”的緊耦合?這就是我們要說的抽象工廠模式。
意圖
提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。
模型圖
邏輯模型:
物理模型:
生活中的例子
抽象工廠的目的是要提供一個創建一系列相關或相互依賴對象的接口,而不需要指定它們具體的類。這種模式可以汽車制造廠所使用的金屬沖壓設備中找到。這種沖壓設備可以制造汽車車身部件。同樣的機械用於沖壓不同的車型的右邊車門、左邊車門、右前擋泥板、左前擋泥板和引擎罩等等。通過使用轉輪來改變沖壓盤,這個機械產生的具體類可以在三分鐘內改變。
抽象工廠之新解
虛擬案例
中國企業需要一項簡單的財務計算:每月月底,財務人員要計算員工的工資。
員工的工資 = (基本工資 + 獎金 - 個人所得稅)。這是一個放之四海皆准的運算法則。
為了簡化系統,我們假設員工基本工資總是4000美金。
中國企業獎金和個人所得稅的計算規則是:
獎金 = 基本工資(4000) * 10%
個人所得稅 = (基本工資 + 獎金) * 40%
我們現在要為此構建一個軟件系統(代號叫Softo),滿足中國企業的需求。
案例分析
獎金(Bonus)、個人所得稅(Tax)的計算是Softo系統的業務規則(Service)。
工資的計算(Calculator)則調用業務規則(Service)來計算員工的實際工資。
工資的計算作為業務規則的前端(或者客戶端Client)將提供給最終使用該系統的用戶(財務人員)使用。
針對中國企業為系統建模
根據上面的分析,為Softo系統建模如下:
則業務規則Service類的代碼如下:
1using System; 2 3namespace ChineseSalary 4{ 5 /**//// <summary> 6 /// 公用的常量 7 /// </summary> 8 public class Constant 9 { 10 public static double BASE_SALARY = 4000; 11 } 12} 1using System; 2 3namespace ChineseSalary 4{ 5 /**//// <summary> 6 /// 計算中國個人獎金 7 /// </summary> 8 public class ChineseBonus 9 { 10 public double Calculate() 11 { 12 return Constant.BASE_SALARY * 0.1; 13 } 14 } 15} 16
客戶端的調用代碼:
1using System; 2 3namespace ChineseSalary 4{ 5 /**//// <summary> 6 /// 計算中國個人所得稅 7 /// </summary> 8 public class ChineseTax 9 { 10 public double Calculate() 11 { 12 return (Constant.BASE_SALARY + (Constant.BASE_SALARY * 0.1)) * 0.4; 13 } 14 } 15} 16
運行程序,輸入的結果如下:
Chinese Salary is:2640
針對美國企業為系統建模
為了拓展國際市場,我們要把該系統移植給美國公司使用。 美國企業的工資計算同樣是: 員工的工資 = 基本工資 + 獎金 - 個人所得稅。
但是他們的獎金和個人所得稅的計算規則不同於中國企業:
美國企業獎金和個人所得稅的計算規則是:
獎金 = 基本工資 * 15 %
個人所得稅 = (基本工資 * 5% + 獎金 * 25%)
根據前面為中國企業建模經驗,我們僅僅將ChineseTax、ChineseBonus修改為AmericanTax、AmericanBonus。 修改後的模型如下:
則業務規則Service類的代碼如下:
1using System; 2 3namespace AmericanSalary 4{ 5 /**//// <summary> 6 /// 公用的常量 7 /// </summary> 8 public class Constant 9 { 10 public static double BASE_SALARY = 4000; 11 } 12} 13 1using System; 2 3namespace AmericanSalary 4{ 5 /**//// <summary> 6 /// 計算美國個人獎金 7 /// </summary> 8 public class AmericanBonus 9 { 10 public double Calculate() 11 { 12 return Constant.BASE_SALARY * 0.1; 13 } 14 } 15} 16 1using System; 2 3namespace AmericanSalary 4{ 5 /**//// <summary> 6 /// 計算美國個人所得稅 7 /// </summary> 8 public class AmericanTax 9 { 10 public double Calculate() 11 { 12 return (Constant.BASE_SALARY + (Constant.BASE_SALARY * 0.1)) * 0.4; 13 } 14 } 15} 16