




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、概述在軟件系統(tǒng)中,經(jīng)常面臨著“一系列相互依賴的對象”的創(chuàng)建工作;同時由于需求的變化,往往存在著更多系列對象的 創(chuàng)建工作。如何應(yīng)對這種變化?如何繞過常規(guī)的對象的創(chuàng)建方法(new),提供一種“封裝機制”來避免客戶程序和這種“多系列具體對象創(chuàng)建工作”的緊耦合? 這就是我們要說的抽象工廠模式。意圖提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口,而無需指定它們具體的類。 模型圖邏輯模型:物理模型:生活中的例子抽象工廠的目的是要提供一個創(chuàng)建一系列相關(guān)或相互依賴 對象的接口,而不需要指定它們具體的類。這種模式可以汽車制造廠所使用的金屬沖壓設(shè)備中找到。這種沖壓設(shè)備可以制造汽車車身部件。同樣的機械用于沖壓不同 的車
2、型的右邊車門、左邊車門、右前擋泥板、左前擋泥板和引擎罩等等。通過使用轉(zhuǎn)輪來改變沖壓盤,這個機械產(chǎn)生的具體類可以在三分鐘內(nèi)改變。抽象工廠之新解虛擬案例中國企業(yè)需要一項簡單的 財務(wù)計算:每月月底,財務(wù)人員要計算員工的工資。員工的工資 = (基本工資 + 獎金 - 個人所得稅)。這是一個放之四海皆準的運算法則。為了簡化系統(tǒng),我們假設(shè)員工基本工資總是4000美金。中國企業(yè)獎 金和個人所得稅的計算規(guī)則是:獎金 = 基本工資(4000) * 10%個人所得稅 = (基本工資 + 獎金) * 40%我們現(xiàn)在要為此構(gòu)建一個軟件系統(tǒng)(代號叫softo),滿足中國企業(yè)的需 求。案例分析獎金(bonus)、個人所得
3、稅(tax)的計算是softo系統(tǒng)的業(yè)務(wù)規(guī)則(service)。 工資的計算(calculator)則調(diào)用業(yè)務(wù)規(guī)則(service)來計算員工的實際工資。工資的計算作為業(yè)務(wù)規(guī)則的前端(或者客 戶端client)將提供給最終使用該系統(tǒng)的用戶(財務(wù)人員)使用。針對中國企業(yè)為系統(tǒng)建模根據(jù)上面的分析,為 softo系統(tǒng)建模如下:則業(yè)務(wù)規(guī)則service類的代碼如下:using system;namespace chinesesalary /*/ summary / 公用的常量 / /summary public class constant public static double base_sala
4、ry = 4000; using system;namespace chinesesalary /*/ summary / 計算中國個人獎金 / /summary public class chinesebonus public double calculate() return constant.base_salary * 0.1; 客戶端的調(diào)用代碼:using system;namespace chinesesalary /*/ summary / 計算中國個人所得稅 / /summary public class chinesetax public double calculate()
5、return (constant.base_salary + (constant.base_salary * 0.1) * 0.4; 運行程序,輸入的結(jié)果如下:chinese salary is:2640針對美國企業(yè)為系統(tǒng)建模 為了拓展國際市場,我們要把該系統(tǒng)移植給美國公司使用。 美國企業(yè)的工資計算同樣是: 員工的工資 = 基本工資 + 獎金 - 個人所得稅。 但是他們的獎金和個人所得稅的計算規(guī)則不同于中國企業(yè):美國企業(yè)獎金和個人所得稅的計算規(guī)則是:獎金 = 基本工資 * 15 %個人所得稅 = (基本工資 * 5% + 獎金 * 25%)根據(jù)前面為中國企業(yè)建模經(jīng) 驗,我們僅僅將chinese
6、tax、chinesebonus修改為americantax、americanbonus。 修改后的模型如下: 則業(yè)務(wù)規(guī)則service類的代碼如下:using system;namespace americansalary /*/ summary / 公用的常量 / /summary public class constant public static double base_salary = 4000; using system;namespace americansalary /*/ summary / 計算美國個人獎金 / /summary public class american
7、bonus public double calculate() return constant.base_salary * 0.1; using system;namespace americansalary /*/ summary / 計算美國個人所得稅 / /summary public class americantax public double calculate() return (constant.base_salary + (constant.base_salary * 0.1) * 0.4; 客戶端的調(diào)用代碼:using system;namespace americansa
8、lary /*/ summary / 客戶端程序調(diào)用 / /summary public class calculator public static void main(string args) americanbonus bonus = new americanbonus(); double bonusvalue = bonus.calculate(); americantax tax = new americantax(); double taxvalue = tax.calculate(); double salary = 4000 + bonusvalue - taxvalue; c
9、onsole.writeline(american salary is: + salary); console.readline(); 運行程序,輸入 的結(jié)果如下:american salary is:2640整合成通用系統(tǒng)讓我們回顧一下該系 統(tǒng)的發(fā)展歷程:最初,我們只考慮將softo系統(tǒng)運行于中國企業(yè)。但隨著maxdo公司業(yè)務(wù)向海外拓展, maxdo需要將該系統(tǒng)移植給美國使用。移植時,maxdo不得不拋棄中國企業(yè)的業(yè)務(wù)規(guī)則類chinesetax和 chinesebonus, 然后為美國企業(yè)新建兩個業(yè)務(wù)規(guī)則類: americantax,americanbonus。最后修改了業(yè)務(wù)規(guī)則調(diào)用calc
10、ulator類。結(jié)果我們發(fā)現(xiàn):每當softo 系統(tǒng)移植的時候,就拋棄原來的類?,F(xiàn)在,如果中國聯(lián)想集團要購買該系統(tǒng),我們不得不再次拋棄americantax,americanbonus,修改回 原來的業(yè)務(wù)規(guī)則。一個可以立即想到的做法就是在系統(tǒng)中保留所有業(yè)務(wù)規(guī)則模型,即保留中國和美國企業(yè)工資運算規(guī)則。通過保留中國企業(yè)和美國企業(yè)的業(yè)務(wù)規(guī)則模型,如果該系統(tǒng)在美國企業(yè)和中國企業(yè)之間切換時,我 們僅僅需要修改caculator類即可。讓移植工作更簡單前面系統(tǒng)的整合問題在于:當系統(tǒng)在客戶在美國和中國企業(yè)間切換時仍然需要修改caculator代碼。一個維護性良 好的系統(tǒng)應(yīng)該遵循“開閉原則”。即:封閉對原來代碼
11、的修改,開放對原來代碼的擴展(如類的繼承,接口的實現(xiàn))我們發(fā)現(xiàn)不論是中國企業(yè)還 是美國企業(yè),他們的業(yè)務(wù)運規(guī)則都采用同樣的計算接口。 于是很自然地想到建立兩個業(yè)務(wù)接口類tax,bonus,然后讓americantax、americanbonus和chinesetax、 chinesebonus分別實現(xiàn)這兩個接口, 據(jù)此修正后的模型如下: 此時客戶端代碼如下:using system;namespace interfacesalary /*/ summary / 客戶端程序調(diào)用 / /summary public class calculator public static void main(s
12、tring args) bonus bonus = new chinesebonus(); double bonusvalue = bonus.calculate(); tax tax = new chinesetax(); double taxvalue = tax.calculate(); double salary = 4000 + bonusvalue - taxvalue; console.writeline(chinaese salary is: + salary); console.readline(); 為業(yè)務(wù)規(guī)則增加工廠方法然而,上面增加的接口幾乎沒有解決任何問題,因為當系統(tǒng)
13、的客戶在美國和中國企業(yè)間切換時caculator代碼仍然需要修改。 只不過修改少了兩處,但是仍然需要修改chinesebonus,chinesetax部分。致命的問題是:我們需要將這個移植工作轉(zhuǎn)包給一個叫 hippo的軟件公司。 由于版權(quán)問題,我們并未提供softo系統(tǒng)的源碼給hippo公司,因此hippo公司根本無法修改calculator,導致實際上移植工作無法進行。為此,我們考慮增加一個工具類(命名為factory),代碼如下:using system;namespace factorysalary /*/ summary / factory類 / /summary public cla
14、ss factory public tax createtax() return new chinesetax(); public bonus createbonus() return new chinesebonus(); 修改后的客戶端代碼:using system;namespace factorysalary /*/ summary / 客戶端程序調(diào)用 / /summary public class calculator public static void main(string args) bonus bonus = new factory().createbonus(); dou
15、ble bonusvalue = bonus.calculate(); tax tax = new factory().createtax(); double taxvalue = tax.calculate(); double salary = 4000 + bonusvalue - taxvalue; console.writeline(chinaese salary is: + salary); console.readline(); 不錯,我們解決了一個大問題,設(shè)想一下:當該系統(tǒng)從中國企業(yè)移植到美國企業(yè)時,我們現(xiàn)在需要做什么?答案是: 對于caculator類我們什么也不用做。我們需要
16、做的是修改factory類,修改結(jié)果如下:using system;namespace factorysalary /*/ summary / factory類 / /summary public class factory public tax createtax() return new americantax(); public bonus createbonus() return new americanbonus(); 為系統(tǒng)增加抽象工廠方法很顯然,前面的解決方案帶來了一個副作用:就是系統(tǒng)不但增加了新的類factory,而且當 系統(tǒng)移植時,移植工作僅僅是轉(zhuǎn)移到factory類上,工作
17、量并沒有任何縮減,而且還是要修改系統(tǒng)的源碼。 從factory類在系統(tǒng)移植時修改的內(nèi)容我們可以看出: 實際上它是專屬于美國企業(yè)或者中國企業(yè)的。名稱上應(yīng)該叫americanfactory,chinesefactory更合適.解決方 案是增加一個抽象工廠類abstractfactory,增加一個靜態(tài)方法,該方法根據(jù)一個配置文件(app.config或者web.config) 一個項(比如factoryname)動態(tài)地判斷應(yīng)該實例化哪個工廠類,這樣,我們就把移植工作轉(zhuǎn)移到了對配置文件的修改。修改后的模型和代碼:抽象工廠類的代碼如下:using system;using system.reflecti
18、on;namespace abstractfactory /*/ summary / abstractfactory類 / /summary public abstract class abstractfactory public static abstractfactory getinstance() string factoryname = constant.str_factoryname.tostring(); abstractfactory instance; if(factoryname = chinesefactory) instance = new chinesefactory(
19、); else if(factoryname = americanfactory) instance = new americanfactory(); else instance = null; return instance; public abstract tax createtax(); public abstract bonus createbonus(); 配置文件:?xml version=1.0 encoding=utf-8 ?configuration appsettings add key=factoryname value=americanfactory/add /apps
20、ettings/configuration 采用上面的解決方案,當系統(tǒng)在美國企業(yè)和中國企業(yè)之間切換時,我們需要做什么移植工作?答案是: 我們僅僅需要修改配置文件,將factoryname的值改為american。修改配置文件的工作很簡單,只要寫一篇幅配置文檔說明 書提供給移植該系統(tǒng)的團隊(比如hippo公司) 就可以方便地切換使該系統(tǒng)運行在美國或中國企業(yè)。最后的修正(不是最終方案) 前面的解決方案幾乎很完美,但是還有一點瑕疵,瑕疵雖小,但可能是致命的??紤]一下,現(xiàn)在日本nec公司決定購買該系統(tǒng),nec公司 的工資的運算規(guī)則遵守的是日本的法律。如果采用上面的系統(tǒng)構(gòu)架,這個移植我們要做哪些工作呢?
21、1. 增加新的業(yè)務(wù)規(guī)則類japanesetax,japanesebonus分別實現(xiàn)tax和bonus接口。2. 修改abstractfactory的getinstance方法,增加else if(factoryname.equals(japanese).注意: 系統(tǒng)中增加業(yè)務(wù)規(guī)則類不是模式所能解決的,無論采用什么設(shè)計模式,japanesetax,japanesebonus總是少不了的。(即增加了新系列產(chǎn)品)我們真正不能接受的是:我們?nèi)匀恍抟薷南到y(tǒng)中原來的類(abstractfactory)。前面提到過該系統(tǒng)的移植工作,我們可 能轉(zhuǎn)包給一個叫hippo的軟件公司。 為了維護版權(quán),未將該系統(tǒng)的源
22、碼提供給hippo公司,那么hippo公司根本無法修改abstractfactory,所以系統(tǒng)移植其實無從談起,或者 說系統(tǒng)移植總要開發(fā)人員親自參與。解決方案是將抽象工廠類中的條件判斷語句,用.net中發(fā)射機制代替,修改如下:using system;using system.reflection;namespace abstractfactory /*/ summary / abstractfactory類 / /summary public abstract class abstractfactory public static abstractfactory getinstance()
23、string factoryname = constant.str_factoryname.tostring(); abstractfactory instance; if(factoryname != ) instance = (abstractfactory)assembly.load(factoryname).createinstance(factoryname); else instance = null; return instance; public abstract tax createtax(); public abstract bonus createbonus(); 這樣,
24、在我們編寫的代碼中就不會出現(xiàn) chinese,american,japanese等這樣的字眼了。小結(jié)最后那幅圖是最終版的系統(tǒng)模型圖。我們發(fā)現(xiàn)作為客戶端角色的calculator僅僅依賴抽象類, 它不必去理解中國和美國企業(yè)具體的業(yè)務(wù)規(guī)則如何實現(xiàn),calculator面對的僅僅是業(yè)務(wù)規(guī)則接口tax和bonus。softo系 統(tǒng)的實際開發(fā)的分工可能是一個團隊專門做業(yè)務(wù)規(guī)則,另一個團隊專門做前端的業(yè)務(wù)規(guī)則組裝。 抽象工廠模式有助于這樣的團隊的分工: 兩個團隊通訊的約定是業(yè)務(wù)接口,由抽象工廠作為紐帶粘合業(yè)務(wù)規(guī)則和前段調(diào)用,大大降低了模塊間的耦合性,提高了團隊開發(fā)效率。完完全全 地理解抽象工廠模式的意義非
25、常重大,可以說對它的理解是你對oop理解上升到一個新的里程碑的重要標志。 學會了用抽象工廠模式編寫框架類,你將理解oop的精華:面向接口編程。應(yīng)對“新對象”抽象工廠模式主要在于應(yīng)對“新系列”的需求變化。其缺點在于難于應(yīng)付“新對象”的需求變動。如果在開 發(fā)中出現(xiàn)了新對象,該如何去解決呢?這個問題并沒有一個好的答案,下面我們看一下李建忠老師的回答:“gof設(shè)計模式中提出過一種 解決方法,即給創(chuàng)建對象的操作增加參數(shù),但這種做法并不能令人滿意。事實上,對于新系列加新對象,就我所知,目前還沒有完美的做法,只有一些演化的思路, 這種變化實在是太劇烈了,因為系統(tǒng)對于新的對象是完全陌生的?!?實現(xiàn)要點抽象工廠
26、將產(chǎn)品對象的創(chuàng)建延遲到它的具體工廠的子類。 如果沒有應(yīng)對“多系列對象創(chuàng)建”的需求變化,則沒有必要使用抽象工廠模式,這時候使用簡單的靜態(tài)工廠完全可以。系列對象指的是這 些對象之間有相互依賴、或作用的關(guān)系,例如游戲開發(fā)場景中的“道路”與“房屋”的依賴,“道路”與“地道”的依賴。抽象工廠模式經(jīng)常 和工廠方法模式共同組合來應(yīng)對“對象創(chuàng)建”的需求變化。通常在運行時刻創(chuàng)建一個具體工廠類的實例,這一具體工廠的創(chuàng)建具有特定實現(xiàn)的 產(chǎn)品對象,為創(chuàng)建不同的產(chǎn)品對象,客戶應(yīng)使用不同的具體工廠。 l 把工廠作為單件,一個應(yīng)用中一般每個產(chǎn)品系列只需一個具體工廠的實例,因此,工廠通常最好實現(xiàn)為一個單件模式。創(chuàng)建產(chǎn)品,抽象工廠僅
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 物流輔助服務(wù)合同范本
- 廣告印刷合同范本
- 個人顧問服務(wù)合同范本
- 2025天津市安全員-A證考試題庫附答案
- 農(nóng)村水泥房拆除合同樣本
- 共同投資種植合同樣本
- 分期買車定金合同樣本
- 學前教育服務(wù)企業(yè)制定與實施新質(zhì)生產(chǎn)力戰(zhàn)略研究報告
- 高品質(zhì)鋨材及鋨加工材企業(yè)制定與實施新質(zhì)生產(chǎn)力戰(zhàn)略研究報告
- 公眾號寫手合同樣本
- 第四單元參考活動3《設(shè)計橡皮章》課件(第二課時) 綜合實踐活動八年級上冊+
- HJ24-2020環(huán)境影響評價技術(shù)導則輸變電
- 鐵路混凝土工程施工質(zhì)量驗收標準
- 河南省鶴壁市2023-2024學年八年級下學期期末數(shù)學試題
- 法制教育課教案(3篇模板)
- 搬家客戶服務(wù)投標書
- 醫(yī)師執(zhí)業(yè)注冊申請審核表(空表)
- GB/T 18488-2024電動汽車用驅(qū)動電機系統(tǒng)
- 不定積分專題試題
- 小學道德與法治活動設(shè)計理念
- 2024年鄭州衛(wèi)生健康職業(yè)學院單招職業(yè)適應(yīng)性測試題庫及答案解析
評論
0/150
提交評論