吳清壽
(武夷學(xué)院數(shù)學(xué)與計(jì)算機(jī)系,福建武夷山 354300)
工廠模式辨析與應(yīng)用研究
吳清壽
(武夷學(xué)院數(shù)學(xué)與計(jì)算機(jī)系,福建武夷山 354300)
通過使用工廠模式封裝了易變對(duì)象,屏蔽了客戶需求變化的負(fù)面影響,解決了客戶和具體對(duì)象的緊耦合。本文討論工廠模式中簡(jiǎn)單工廠模式、工廠方法模式和抽象工廠模式的基本結(jié)構(gòu),并對(duì)其適用場(chǎng)景和優(yōu)缺點(diǎn)進(jìn)行深入剖析。為進(jìn)一步降低客戶對(duì)工廠對(duì)象的依賴,用1NET中的反射機(jī)制和配置文件動(dòng)態(tài)地創(chuàng)建工廠對(duì)象。
設(shè)計(jì)模式;工廠模式;設(shè)計(jì)原則;反射;配置文件
用面向?qū)ο蠹夹g(shù)開發(fā)應(yīng)用系統(tǒng),實(shí)例化對(duì)象是不可避免的而且是很頻繁的。當(dāng)所實(shí)例化的對(duì)象是穩(wěn)定的,也就是不會(huì)經(jīng)常變化,這時(shí)并沒有問題。當(dāng)所實(shí)例化的對(duì)象因需求變化而經(jīng)常發(fā)生變化,這將造成客戶代碼的不穩(wěn)定,因?yàn)槊恳淮螌?duì)象的變更都需要修改客戶代碼。需求變化可能不僅僅是變更對(duì)象,還可能需要增刪對(duì)象,此時(shí)原來的系統(tǒng)將發(fā)生劇烈變化,需要修改的部分不止是一行或幾行代碼,而可能是結(jié)構(gòu)上的變化,這種修改有時(shí)是災(zāi)難性的,因?yàn)榭赡芤鹣到y(tǒng)中多個(gè)子系統(tǒng)的變化。
面向?qū)ο蟮囊粋€(gè)重要設(shè)計(jì)原則就是封裝變化點(diǎn),封裝指的是任何形式的隱藏,包括數(shù)據(jù)隱藏、實(shí)現(xiàn)隱藏、類隱藏、設(shè)計(jì)隱藏和實(shí)例化隱藏,本文特指實(shí)例化隱藏。如果有一個(gè)組件能夠用于封裝對(duì)象的創(chuàng)建和管理,而客戶只和該組件交互,這樣將大幅度減少客戶對(duì)具體對(duì)象的依賴,從而達(dá)到客戶代碼的相對(duì)穩(wěn)定。設(shè)計(jì)模式中的工廠模式為解決該問題提供了一種可能,它通過專門的類用于實(shí)例化并獲得對(duì)象,這個(gè)類稱為工廠。根據(jù)實(shí)例化的時(shí)機(jī)、所創(chuàng)建對(duì)象的層次結(jié)構(gòu)和關(guān)聯(lián)度,這里把工廠模式劃分為簡(jiǎn)單工廠模式、工廠方法模式和抽象工廠模式。
簡(jiǎn)單工廠模式的意圖:實(shí)例化對(duì)象,而不需要客戶了解這個(gè)對(duì)象屬于哪個(gè)具體的子類[1-2]。通常由一個(gè)工廠對(duì)象決定創(chuàng)建出哪一種產(chǎn)品類的實(shí)例,簡(jiǎn)單工廠模式并不屬于G OF23種模式,通常作為工廠方法模式的一個(gè)特例加以討論,這里將其單獨(dú)作為一種模式討論有助于更全面把握工廠模式的本質(zhì)。
從圖1中可以看到,客戶 (Client)扮演著產(chǎn)品消費(fèi)者的角色,它只依賴于工廠 (Factory)和抽象產(chǎn)品(Product),但它不知道也不需要知道到底有哪些具體產(chǎn)品,其所需的一切產(chǎn)品由工廠提供,這種結(jié)構(gòu)解耦了客戶和具體產(chǎn)品類。當(dāng)具體產(chǎn)品類發(fā)生變化時(shí),客戶中的代碼無需修改,這符合開閉原則。
對(duì)工廠而言,它必須知道所有的產(chǎn)品,它還負(fù)責(zé)創(chuàng)建產(chǎn)品并將產(chǎn)品提供給客戶,如果產(chǎn)品類型發(fā)生變更,則需要修改工廠。
工廠方法模式的意圖:定義一個(gè)用于創(chuàng)建對(duì)象的接口,讓子類決定實(shí)例化哪一個(gè)類。工廠方法使一個(gè)類的實(shí)例化延遲到其子類[1,4]。
圖1 簡(jiǎn)單工廠模式結(jié)構(gòu)
在圖2中,Creator聲明工廠方法FactoryMethod()返回一個(gè)Product類型的對(duì)象,ConcreteCreator重定義工廠方法以返回一個(gè)ConcreteProduct實(shí)例。這里的核心是工廠方法FactoryMethod(),在Creator類中它是抽象的,而在ConcreteCreator類中它將根據(jù)需要實(shí)例化具體產(chǎn)品類并將其返回給客戶。這樣的好處是當(dāng)增加一個(gè)新產(chǎn)品,原來的ConcreteCreator類不需要修改,所要做的工作就是再增加一個(gè)ConcreteCreator類并實(shí)現(xiàn)Facto2 ryMethod()方法,用以創(chuàng)建和返回新產(chǎn)品。
圖2 工廠方法模式結(jié)構(gòu)
抽象工廠模式的意圖:提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對(duì)象的接口,而無需指定它們具體的類[1,4]。在圖3中,AbstractProductA和AbstractProductB代表多個(gè)產(chǎn)品系列的抽象,具體產(chǎn)品則由具體工廠創(chuàng)建,Client只使用AbstractProduct和AbstractFactory類聲明的接口,無需了解具體產(chǎn)品細(xì)節(jié)。所以,抽象工廠的主要作用就是提供一種封裝機(jī)制來解決客戶和多系列具體對(duì)象創(chuàng)建工作的緊耦合。
通過對(duì)三個(gè)模式的共性和差異進(jìn)行探討,了解其主要應(yīng)用場(chǎng)景及優(yōu)缺點(diǎn),將有助于在具體的系統(tǒng)設(shè)計(jì)中選擇合適的設(shè)計(jì)模式。
工廠模式屬于創(chuàng)建型模式,其最核心的功能就是封裝具體類的信息并隱藏這些類實(shí)例的創(chuàng)建過程,減少系統(tǒng)中對(duì)象之間的緊耦合關(guān)系,降低因需求頻繁變化引起的系統(tǒng)框架變動(dòng)和代碼修改,為系統(tǒng)擴(kuò)展留下空間,從而使得系統(tǒng)更有彈性。工廠模式遵循針對(duì)接口編程的原則,用接口代替將來可能變化的對(duì)象,依靠工廠類或工廠方法負(fù)責(zé)具體對(duì)象創(chuàng)建工作,降低客戶對(duì)具體對(duì)象的依賴性,滿足系統(tǒng)變化的需求。
圖3 抽象工廠模式結(jié)構(gòu)
簡(jiǎn)單工廠模式中工廠類負(fù)責(zé)具體產(chǎn)品的實(shí)例化工作,其優(yōu)點(diǎn)是隔離了客戶端和具體產(chǎn)品,使得客戶端相對(duì)獨(dú)立于具體產(chǎn)品的創(chuàng)建過程,在系統(tǒng)引入新產(chǎn)品時(shí)無需修改客戶端,但需要修改工廠類。
工廠方法模式利用多態(tài)性對(duì)簡(jiǎn)單工廠模式進(jìn)行了抽象和推廣,克服了簡(jiǎn)單工廠模式中需要經(jīng)常修改工廠類的缺點(diǎn)。原來的工廠類變成了抽象類,并給出具體工廠子類要實(shí)現(xiàn)的接口即工廠方法,本身不再?zèng)Q定具體產(chǎn)品的實(shí)例化,而是由子類決定創(chuàng)建哪個(gè)具體產(chǎn)品。當(dāng)引入新產(chǎn)品,原來的具體工廠保持不變,只需增加一個(gè)新的具體工廠。這種結(jié)構(gòu)符合開閉原則,為具有穩(wěn)定接口的產(chǎn)品系列頻繁變化提供了封裝機(jī)制。工廠方法模式雖然解耦了客戶端和具體產(chǎn)品,但增加了客戶端和具體工廠的耦合,我們可以利用1NET中的反射機(jī)制來解決這種耦合問題。
抽象工廠模式提供一個(gè)抽象接口 (接口或抽象類)用來創(chuàng)建產(chǎn)品家族,其具體子類提供負(fù)責(zé)在抽象工廠中創(chuàng)建產(chǎn)品的方法,通常以工廠方法來實(shí)現(xiàn)。抽象工廠模式使得易于更換產(chǎn)品系列,一個(gè)具體工廠對(duì)應(yīng)一個(gè)產(chǎn)品系列,在系統(tǒng)中只需改變具體工廠就可以使用不同的產(chǎn)品。抽象工廠模式難以支持新種類的產(chǎn)品,因?yàn)槌橄蠊S接口確定了可以被創(chuàng)建的產(chǎn)品集合,增加新產(chǎn)品就意味著需要擴(kuò)展工廠接口,這將造成抽象工廠和所有子類都需要改變接口。
另外,工廠方法模式屬于類創(chuàng)建型模式,它使用繼承改變被實(shí)例化的類,而抽象工廠模式屬于對(duì)象創(chuàng)建型模式,它將實(shí)例化委托給另一個(gè)對(duì)象。
反射 (Reflection)是1NET中的重要機(jī)制,通過反射,系統(tǒng)具有審查元數(shù)據(jù)并收集關(guān)于它的類型信息的能力,可以在運(yùn)行時(shí)獲得1NET中每一個(gè)類型的成員,包括方法、屬性、事件以及構(gòu)造函數(shù)等。獲得了構(gòu)造函數(shù)的信息,即可動(dòng)態(tài)創(chuàng)建對(duì)象,該功能為簡(jiǎn)化工廠模式應(yīng)用提供了一種解決方案。
為了避免將類型名稱硬編碼在代碼中,可以將類型名存儲(chǔ)在ASP1NET應(yīng)用程序的web1config文件中或Windows應(yīng)用程序的app1config文件中。類型名存儲(chǔ)為鍵/值對(duì)的形式,可以在運(yùn)行時(shí)使用key查找存儲(chǔ)在AppSettings屬性中的值。在應(yīng)用程序的app1config文件的
利用CreateInstance方法可以動(dòng)態(tài)創(chuàng)建工廠對(duì)象,其中程序集名稱一般比較穩(wěn)定,因而可以直接在代碼中嵌入。而根據(jù)不同的需求,客戶所使用的工廠經(jīng)常發(fā)生變化,這時(shí),可以通過讀取配置文件來獲得工廠類型名稱,當(dāng)需要更換工廠時(shí),只需更改配置文件中value即可,或者在代碼中更改key所對(duì)應(yīng)的工廠類型名稱。
從以上代碼可以看出,客戶沒有與具體產(chǎn)品耦合,也沒有與具體工廠耦合,反射機(jī)制通過動(dòng)態(tài)創(chuàng)建對(duì)象使得程序框架更加具有彈性和靈活性。在對(duì)于簡(jiǎn)單工廠模式、工廠方法模式和抽象工廠模式的應(yīng)用中,雖然細(xì)節(jié)上略有不同,但基本原理和操作方式與上述過程類似。
實(shí)際上所有的創(chuàng)建型模式都是工廠模式,因?yàn)樗鼈兯鉀Q的主要問題就是對(duì)象的創(chuàng)建和管理工作。針對(duì)如何創(chuàng)建對(duì)象、誰來創(chuàng)建對(duì)象、何時(shí)創(chuàng)建對(duì)象等問題,工廠模式提供了一些頗具彈性的解決辦法,從而有助于保持系統(tǒng)中對(duì)象內(nèi)聚、解耦和可測(cè)試。
在遵循面向?qū)ο笤O(shè)計(jì)原則方面,開閉原則 (OCP)、依賴倒置原則 (DIP)和Liskov替換原則 (LSP)為工廠模式實(shí)施提供了主要根據(jù)[3,5]。開閉原則使得系統(tǒng)更具健壯性、可維護(hù)性和可重用性,依賴倒置原則指出了工廠模式實(shí)現(xiàn)的主要技術(shù)手段之一,即使得高層策略模塊在創(chuàng)建類的實(shí)例時(shí)無需依賴于這些類的具體實(shí)現(xiàn),Liskov替換原則中子類型的可替換性使得使用基類型表示的模塊在無需修改的情況下就可以擴(kuò)展,增加了工廠模式處理多變對(duì)象的靈活性。
工廠模式雖然具有很多優(yōu)點(diǎn),但會(huì)增加設(shè)計(jì)的復(fù)雜性,如為了創(chuàng)建一個(gè)新類,就需要該對(duì)象的接口類及具體實(shí)現(xiàn)類和創(chuàng)建該對(duì)象的工廠類。所以,如果要實(shí)例化的對(duì)象是穩(wěn)定的或相對(duì)穩(wěn)定的,這時(shí)并不需要使用工廠模式。
使用反射機(jī)制可以動(dòng)態(tài)地創(chuàng)建實(shí)例,在程序中合理地使用反射可以使程序更加靈活。但是使用反射動(dòng)態(tài)綁定時(shí)也需要犧牲性能,所以在程序中也要綜合考慮這些方面的因素來決定是否要用。
[1]Gamma E,Helm R,Johnson R,et al.設(shè)計(jì)模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)[M].北京:機(jī)械工業(yè)出版社,2000.
[2]甑鐳..NET與設(shè)計(jì)模式[M].北京:電子工業(yè)出版社,2005.
[3]Martin E,Martin M.敏捷軟件開發(fā):原則、模式與實(shí)踐(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è)計(jì)與應(yīng)用[J].計(jì)算機(jī)工程與設(shè)計(jì),2008,29(2):454-455.
[7]湯國(guó)華,葉丹,徐罡.基于設(shè)計(jì)模式的通用數(shù)據(jù)庫(kù)視圖生成方法[J].計(jì)算機(jī)輔助工程,2008,17(1):47.
[8]何泓偉,曲朝陽(yáng).設(shè)計(jì)模式混合的構(gòu)造方法研究及應(yīng)用[J].計(jì)算機(jī)工程與設(shè)計(jì),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é)與計(jì)算機(jī)系講師,碩士,從事軟件工程、1NET技術(shù)及分布式系統(tǒng)設(shè)計(jì)研究。
長(zhǎng)春師范大學(xué)學(xué)報(bào)2011年2期