吳清壽
(武夷學(xué)院數(shù)學(xué)與計算機系,福建武夷山 354300)
工廠模式辨析與應(yīng)用研究
吳清壽
(武夷學(xué)院數(shù)學(xué)與計算機系,福建武夷山 354300)
通過使用工廠模式封裝了易變對象,屏蔽了客戶需求變化的負面影響,解決了客戶和具體對象的緊耦合。本文討論工廠模式中簡單工廠模式、工廠方法模式和抽象工廠模式的基本結(jié)構(gòu),并對其適用場景和優(yōu)缺點進行深入剖析。為進一步降低客戶對工廠對象的依賴,用1NET中的反射機制和配置文件動態(tài)地創(chuàng)建工廠對象。
設(shè)計模式;工廠模式;設(shè)計原則;反射;配置文件
用面向?qū)ο蠹夹g(shù)開發(fā)應(yīng)用系統(tǒng),實例化對象是不可避免的而且是很頻繁的。當(dāng)所實例化的對象是穩(wěn)定的,也就是不會經(jīng)常變化,這時并沒有問題。當(dāng)所實例化的對象因需求變化而經(jīng)常發(fā)生變化,這將造成客戶代碼的不穩(wěn)定,因為每一次對象的變更都需要修改客戶代碼。需求變化可能不僅僅是變更對象,還可能需要增刪對象,此時原來的系統(tǒng)將發(fā)生劇烈變化,需要修改的部分不止是一行或幾行代碼,而可能是結(jié)構(gòu)上的變化,這種修改有時是災(zāi)難性的,因為可能引起系統(tǒng)中多個子系統(tǒng)的變化。
面向?qū)ο蟮囊粋€重要設(shè)計原則就是封裝變化點,封裝指的是任何形式的隱藏,包括數(shù)據(jù)隱藏、實現(xiàn)隱藏、類隱藏、設(shè)計隱藏和實例化隱藏,本文特指實例化隱藏。如果有一個組件能夠用于封裝對象的創(chuàng)建和管理,而客戶只和該組件交互,這樣將大幅度減少客戶對具體對象的依賴,從而達到客戶代碼的相對穩(wěn)定。設(shè)計模式中的工廠模式為解決該問題提供了一種可能,它通過專門的類用于實例化并獲得對象,這個類稱為工廠。根據(jù)實例化的時機、所創(chuàng)建對象的層次結(jié)構(gòu)和關(guān)聯(lián)度,這里把工廠模式劃分為簡單工廠模式、工廠方法模式和抽象工廠模式。
簡單工廠模式的意圖:實例化對象,而不需要客戶了解這個對象屬于哪個具體的子類[1-2]。通常由一個工廠對象決定創(chuàng)建出哪一種產(chǎn)品類的實例,簡單工廠模式并不屬于G OF23種模式,通常作為工廠方法模式的一個特例加以討論,這里將其單獨作為一種模式討論有助于更全面把握工廠模式的本質(zhì)。
從圖1中可以看到,客戶 (Client)扮演著產(chǎn)品消費者的角色,它只依賴于工廠 (Factory)和抽象產(chǎn)品(Product),但它不知道也不需要知道到底有哪些具體產(chǎn)品,其所需的一切產(chǎn)品由工廠提供,這種結(jié)構(gòu)解耦了客戶和具體產(chǎn)品類。當(dāng)具體產(chǎn)品類發(fā)生變化時,客戶中的代碼無需修改,這符合開閉原則。
對工廠而言,它必須知道所有的產(chǎn)品,它還負責(zé)創(chuàng)建產(chǎn)品并將產(chǎn)品提供給客戶,如果產(chǎn)品類型發(fā)生變更,則需要修改工廠。
工廠方法模式的意圖:定義一個用于創(chuàng)建對象的接口,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到其子類[1,4]。
圖1 簡單工廠模式結(jié)構(gòu)
在圖2中,Creator聲明工廠方法FactoryMethod()返回一個Product類型的對象,ConcreteCreator重定義工廠方法以返回一個ConcreteProduct實例。這里的核心是工廠方法FactoryMethod(),在Creator類中它是抽象的,而在ConcreteCreator類中它將根據(jù)需要實例化具體產(chǎn)品類并將其返回給客戶。這樣的好處是當(dāng)增加一個新產(chǎn)品,原來的ConcreteCreator類不需要修改,所要做的工作就是再增加一個ConcreteCreator類并實現(xiàn)Facto2 ryMethod()方法,用以創(chuàng)建和返回新產(chǎn)品。
圖2 工廠方法模式結(jié)構(gòu)
抽象工廠模式的意圖:提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口,而無需指定它們具體的類[1,4]。在圖3中,AbstractProductA和AbstractProductB代表多個產(chǎn)品系列的抽象,具體產(chǎn)品則由具體工廠創(chuàng)建,Client只使用AbstractProduct和AbstractFactory類聲明的接口,無需了解具體產(chǎn)品細節(jié)。所以,抽象工廠的主要作用就是提供一種封裝機制來解決客戶和多系列具體對象創(chuàng)建工作的緊耦合。
通過對三個模式的共性和差異進行探討,了解其主要應(yīng)用場景及優(yōu)缺點,將有助于在具體的系統(tǒng)設(shè)計中選擇合適的設(shè)計模式。
工廠模式屬于創(chuàng)建型模式,其最核心的功能就是封裝具體類的信息并隱藏這些類實例的創(chuàng)建過程,減少系統(tǒng)中對象之間的緊耦合關(guān)系,降低因需求頻繁變化引起的系統(tǒng)框架變動和代碼修改,為系統(tǒng)擴展留下空間,從而使得系統(tǒng)更有彈性。工廠模式遵循針對接口編程的原則,用接口代替將來可能變化的對象,依靠工廠類或工廠方法負責(zé)具體對象創(chuàng)建工作,降低客戶對具體對象的依賴性,滿足系統(tǒng)變化的需求。
圖3 抽象工廠模式結(jié)構(gòu)
簡單工廠模式中工廠類負責(zé)具體產(chǎn)品的實例化工作,其優(yōu)點是隔離了客戶端和具體產(chǎn)品,使得客戶端相對獨立于具體產(chǎn)品的創(chuàng)建過程,在系統(tǒng)引入新產(chǎn)品時無需修改客戶端,但需要修改工廠類。
工廠方法模式利用多態(tài)性對簡單工廠模式進行了抽象和推廣,克服了簡單工廠模式中需要經(jīng)常修改工廠類的缺點。原來的工廠類變成了抽象類,并給出具體工廠子類要實現(xiàn)的接口即工廠方法,本身不再決定具體產(chǎn)品的實例化,而是由子類決定創(chuàng)建哪個具體產(chǎn)品。當(dāng)引入新產(chǎn)品,原來的具體工廠保持不變,只需增加一個新的具體工廠。這種結(jié)構(gòu)符合開閉原則,為具有穩(wěn)定接口的產(chǎn)品系列頻繁變化提供了封裝機制。工廠方法模式雖然解耦了客戶端和具體產(chǎn)品,但增加了客戶端和具體工廠的耦合,我們可以利用1NET中的反射機制來解決這種耦合問題。
抽象工廠模式提供一個抽象接口 (接口或抽象類)用來創(chuàng)建產(chǎn)品家族,其具體子類提供負責(zé)在抽象工廠中創(chuàng)建產(chǎn)品的方法,通常以工廠方法來實現(xiàn)。抽象工廠模式使得易于更換產(chǎn)品系列,一個具體工廠對應(yīng)一個產(chǎn)品系列,在系統(tǒng)中只需改變具體工廠就可以使用不同的產(chǎn)品。抽象工廠模式難以支持新種類的產(chǎn)品,因為抽象工廠接口確定了可以被創(chuàng)建的產(chǎn)品集合,增加新產(chǎn)品就意味著需要擴展工廠接口,這將造成抽象工廠和所有子類都需要改變接口。
另外,工廠方法模式屬于類創(chuàng)建型模式,它使用繼承改變被實例化的類,而抽象工廠模式屬于對象創(chuàng)建型模式,它將實例化委托給另一個對象。
反射 (Reflection)是1NET中的重要機制,通過反射,系統(tǒng)具有審查元數(shù)據(jù)并收集關(guān)于它的類型信息的能力,可以在運行時獲得1NET中每一個類型的成員,包括方法、屬性、事件以及構(gòu)造函數(shù)等。獲得了構(gòu)造函數(shù)的信息,即可動態(tài)創(chuàng)建對象,該功能為簡化工廠模式應(yīng)用提供了一種解決方案。
為了避免將類型名稱硬編碼在代碼中,可以將類型名存儲在ASP1NET應(yīng)用程序的web1config文件中或Windows應(yīng)用程序的app1config文件中。類型名存儲為鍵/值對的形式,可以在運行時使用key查找存儲在AppSettings屬性中的值。在應(yīng)用程序的app1config文件的
利用CreateInstance方法可以動態(tài)創(chuàng)建工廠對象,其中程序集名稱一般比較穩(wěn)定,因而可以直接在代碼中嵌入。而根據(jù)不同的需求,客戶所使用的工廠經(jīng)常發(fā)生變化,這時,可以通過讀取配置文件來獲得工廠類型名稱,當(dāng)需要更換工廠時,只需更改配置文件中value即可,或者在代碼中更改key所對應(yīng)的工廠類型名稱。
從以上代碼可以看出,客戶沒有與具體產(chǎn)品耦合,也沒有與具體工廠耦合,反射機制通過動態(tài)創(chuàng)建對象使得程序框架更加具有彈性和靈活性。在對于簡單工廠模式、工廠方法模式和抽象工廠模式的應(yīng)用中,雖然細節(jié)上略有不同,但基本原理和操作方式與上述過程類似。
實際上所有的創(chuàng)建型模式都是工廠模式,因為它們所解決的主要問題就是對象的創(chuàng)建和管理工作。針對如何創(chuàng)建對象、誰來創(chuàng)建對象、何時創(chuàng)建對象等問題,工廠模式提供了一些頗具彈性的解決辦法,從而有助于保持系統(tǒng)中對象內(nèi)聚、解耦和可測試。
在遵循面向?qū)ο笤O(shè)計原則方面,開閉原則 (OCP)、依賴倒置原則 (DIP)和Liskov替換原則 (LSP)為工廠模式實施提供了主要根據(jù)[3,5]。開閉原則使得系統(tǒng)更具健壯性、可維護性和可重用性,依賴倒置原則指出了工廠模式實現(xiàn)的主要技術(shù)手段之一,即使得高層策略模塊在創(chuàng)建類的實例時無需依賴于這些類的具體實現(xiàn),Liskov替換原則中子類型的可替換性使得使用基類型表示的模塊在無需修改的情況下就可以擴展,增加了工廠模式處理多變對象的靈活性。
工廠模式雖然具有很多優(yōu)點,但會增加設(shè)計的復(fù)雜性,如為了創(chuàng)建一個新類,就需要該對象的接口類及具體實現(xiàn)類和創(chuàng)建該對象的工廠類。所以,如果要實例化的對象是穩(wěn)定的或相對穩(wěn)定的,這時并不需要使用工廠模式。
使用反射機制可以動態(tài)地創(chuàng)建實例,在程序中合理地使用反射可以使程序更加靈活。但是使用反射動態(tài)綁定時也需要犧牲性能,所以在程序中也要綜合考慮這些方面的因素來決定是否要用。
[1]Gamma E,Helm R,Johnson R,et al.設(shè)計模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)[M].北京:機械工業(yè)出版社,2000.
[2]甑鐳..NET與設(shè)計模式[M].北京:電子工業(yè)出版社,2005.
[3]Martin E,Martin M.敏捷軟件開發(fā):原則、模式與實踐(C#版)[M].北京:人民郵電出版社,2008.
[4]Gamma E,Helm R,Johnson R,et al.Design patterns:element s of reusable object oriented systems[M].Boston:Addison Wesley,1995.
[5]閻宏.Java與模式[M].北京:電子工業(yè)出版社,2002.
[6]郭曉峰,姚世軍,尹祖?zhèn)?基于.NET的Web應(yīng)用框架的設(shè)計與應(yīng)用[J].計算機工程與設(shè)計,2008,29(2):454-455.
[7]湯國華,葉丹,徐罡.基于設(shè)計模式的通用數(shù)據(jù)庫視圖生成方法[J].計算機輔助工程,2008,17(1):47.
[8]何泓偉,曲朝陽.設(shè)計模式混合的構(gòu)造方法研究及應(yīng)用[J].計算機工程與設(shè)計,2007,28(5):999-1000.
Analysis and Applied Research on Factory Patterns
WU Qing-shou
(Department of Mathematics and Computer Science of Wuyi University,Wuyishan 354300,China)
By the factory patterns,the volatile objects are sealed,negative impacts of changeable customer needs are shield2 ed,and the problem of tightly coupling between customers and concrete objects is resolved.The basic structures of simple factory pattern,factory method and abstract factory pattern in the factory patterns are discussed.In-depth analysison its ap2 plicability to scenes and advantage and weakness is also conducted.T o further reduce customersπreliance on factoryobjects,factory objects are dynamically created based on the.NET reflection mechanism and the configuration file.
design pattern;factory pattern;design principles;reflection;configuration file
TP31115
A
1008-178X(2011)02-0030-04
2011-01-10
吳清壽 (1977-),男,福建莆田人,武夷學(xué)院數(shù)學(xué)與計算機系講師,碩士,從事軟件工程、1NET技術(shù)及分布式系統(tǒng)設(shè)計研究。