采用上面的解決方案,當系統在美國企業和中國企業之間切換時,我們需要做什麼移植工作?
答案是: 我們僅僅需要修改配置文件,將factoryName的值改為American。
修改配置文件的工作很簡單,只要寫一篇幅配置文檔說明書提供給移植該系統的團隊(比如Hippo公司) 就可以方便地切換使該系統運行在美國或中國企業。
最後的修正(不是最終方案)
前面的解決方案幾乎很完美,但是還有一點瑕疵,瑕疵雖小,但可能是致命的。
考慮一下,現在日本NEC公司決定購買該系統,NEC公司的工資的運算規則遵守的是日本的法律。如果采用上面的系統構架,這個移植我們要做哪些工作呢?
1. 增加新的業務規則類JapaneseTax,JapaneseBonus分別實現Tax和Bonus接口。
2. 修改AbstractFactory的getInstance方法,增加else if(factoryName.equals("Japanese")){....
注意: 系統中增加業務規則類不是模式所能解決的,無論采用什麼設計模式,JapaneseTax,JapaneseBonus總是少不了的。(即增加了新系列產品)
我們真正不能接受的是:我們仍然修要修改系統中原來的類(AbstractFactory)。前面提到過該系統的移植工作,我們可能轉包給一個叫Hippo的軟件公司。為了維護版權,未將該系統的源碼提供給Hippo公司,那麼Hippo公司根本無法修改AbstractFactory,所以系統移植其實無從談起,或者說系統移植總要開發人員親自參與。
解決方案是將抽象工廠類中的條件判斷語句,用.Net中發射機制代替,修改如下:
1using System;
2using System.Reflection;
3
4namespace AbstractFactory
5{
6 /**//// <summary>
7 /// AbstractFactory類
8 /// </summary>
9 public abstract class AbstractFactory
10 {
11 public static AbstractFactory GetInstance()
12 {
13 string factoryName = Constant.STR_FACTORYNAME.ToString();
14
15 AbstractFactory instance;
16
17 if(factoryName != "")
18 instance = (AbstractFactory)Assembly.Load(factoryName).CreateInstance(factoryName);
19 else
20 instance = null;
21
22 return instance;
23 }
24
25 public abstract Tax CreateTax();
26
27 public abstract Bonus CreateBonus();
28 }
29}
30
這樣,在我們編寫的代碼中就不會出現Chinese,American,Japanese等這樣的字眼了。
小結
最後那幅圖是最終版的系統模型圖。我們發現作為客戶端角色的Calculator僅僅依賴抽象類, 它不必去理解中國和美國企業具體的業務規則如何實現,Calculator面對的僅僅是業務規則接口Tax和Bonus。
Softo系統的實際開發的分工可能是一個團隊專門做業務規則,另一個團隊專門做前端的業務規則組裝。抽象工廠模式有助於這樣的團隊的分工: 兩個團隊通訊的約定是業務接口,由抽象工廠作為紐帶粘合業務規則和前段調用,大大降低了模塊間的耦合性,提高了團隊開發效率。
完完全全地理解抽象工廠模式的意義非常重大,可以說對它的理解是你對OOP理解上升到一個新的裡程碑的重要標志。學會了用抽象工廠模式編寫框架類,你將理解OOP的精華:面向接口編程。