由淺入深學(xué)“工廠模式”_第1頁
由淺入深學(xué)“工廠模式”_第2頁
由淺入深學(xué)“工廠模式”_第3頁
由淺入深學(xué)“工廠模式”_第4頁
由淺入深學(xué)“工廠模式”_第5頁
已閱讀5頁,還剩14頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、由淺入深學(xué)工廠模式”(1)2007-03-2517:131、傳授設(shè)計模式中存在的問題我個人最近對設(shè)計模式中的工廠模式進行了比較深入的學(xué)習(xí),通過學(xué)習(xí)感悟出,現(xiàn)在很多設(shè)計模式傳道者,在講述設(shè)計模式的過程中存在一些問題,使得設(shè)計模式變得很難理解。設(shè)計模式本身很抽象,但是這些傳道者在講述的過程中,將一個抽象的東西講的更抽象,從而使我們望而卻步。有些人在講述的時候,沒有考慮讀者的注意力。比如我在看C#設(shè)計模式的時候,在講述抽象工廠模式的時候,直接就進入了一個示例,而且這個例子比較復(fù)雜,涉及了比較多的概念、術(shù)語,而且還有算法要處理。但是這些和要講述的核心內(nèi)容無關(guān),我想要看懂他的示例就要將這個東西都搞懂,就

2、分散了我的注意力。我個人總結(jié),學(xué)習(xí)設(shè)計模式的方法是,首先找到一個突破口,比如可以先學(xué)習(xí)構(gòu)造型模式中簡單的模式,將它理解、熟練應(yīng)用。通過對一、兩個模式有一個深入的認識之后,再學(xué)習(xí)其它比較復(fù)雜一點的模式就容易多了,這是一種迭代的思想在學(xué)習(xí)中的應(yīng)用。另外學(xué)習(xí)任何一種設(shè)計模式的過程應(yīng)該是具體-抽象-再具體這個的一個過程。這句話的意思是首先通過一個比較具體一點的例子來幫助理解設(shè)計模式,在理解之后將你的理解擴展到解決這一類問題,上升到一定的理論高度。然后就是再到具體,也就是應(yīng)用設(shè)計模式,應(yīng)用理論解決自己遇到的實際問題。2、學(xué)習(xí)工廠模式的預(yù)備知識:首先聲明這些預(yù)備知識并不是工廠模式僅僅需要,因為我先講述工廠

3、模式,所以在學(xué)習(xí)工廠模式之前將這些問題提出。Upcasting:Upcasting中文翻譯有好幾個,比如向上類型轉(zhuǎn)換、向上轉(zhuǎn)型、上溯造型。我個人比較喜歡向上轉(zhuǎn)型這個翻譯,即簡單又含義明確。向上轉(zhuǎn)型這個概念,我在BruceEckeI的ThinkinginC+ThinkinginJava中都看到過,我不是很確定這個概念是否是他提出來的。向上轉(zhuǎn)型是把一個派生類當作它的基類使用。我們將一個更特殊的類型轉(zhuǎn)換到一個更常規(guī)的類型,這當然是安全的。派生類是基類的一個超集。它可以包含比基類更多的方法,但它至少包含了基類的方法。向上轉(zhuǎn)型給我們帶來的好處就是我們可以將不同的派生通過一種統(tǒng)一的方式進行處理。向上轉(zhuǎn)型帶

4、來的弊端就是我們向上轉(zhuǎn)型的過程會丟失派生類的接口。既然有向上轉(zhuǎn)型,也就有向下轉(zhuǎn)型即DownCasting,我們在此不做詳細討論。下面使用一個例子來示例向上轉(zhuǎn)型。publicclassBasepublicvoidTest()(OK);publicclassDerive:Baseprivatevoidbutton1_Click(objectsender,e)Baseb=newDerive。;();多態(tài)我不敢想象離開了多態(tài)后的設(shè)計模式是一個什么樣子。什么是多態(tài),我喜歡總結(jié)這樣一句話來回答這個問題,一個接口,多種實現(xiàn)”。注意這里的接口不僅僅表示Interface關(guān)鍵字,是廣義上的接口。在C#中實現(xiàn)接口

5、我們有兩種途徑,一種是借助繼承來實現(xiàn),一種是借助Interface來實現(xiàn)。3、工廠設(shè)計模式理論概述工廠模式具體包括了簡單工廠、工廠方法、抽象工廠,它們是按照從簡單到復(fù)雜的順序排列的,屬于設(shè)計模式中的創(chuàng)建型,其中簡單工廠并不屬于GOF的23中模式。但是它是理解其它的工廠模式的一個很好的基礎(chǔ),所以很多人在講述設(shè)計模式的時候會提到簡單工廠模式。創(chuàng)建型模式關(guān)注的是對象的創(chuàng)建,創(chuàng)建型模式將創(chuàng)建對象的過程進行了抽象,也可以理解為將創(chuàng)建對象的過程進行了封裝,作為客戶程序僅僅需要去使用對象,而不再關(guān)心創(chuàng)建對象過程中的邏輯。不使用任何模式我們現(xiàn)在有這樣的一個設(shè)計,影像家電(VideoWiring)包括了DVDV

6、CDb在基類VideoWiring中有PlayVideo方法,子類重載了這個方法。我們?nèi)绾蝸碚{(diào)用PlayVideo進行播放呢。我們可以看到下面的代碼可以實現(xiàn)。下面是調(diào)用對象的方法進行播放的代碼:publicabstractclassVideoWiringpublicabstractstringPlayVideo。;publicclassVCD:VideoWiringpublicoverridestringPlayVideo()return正在播放播放VCD;publicclassDVD:VideoWiringpublicoverridestringPlayVideo()return正在播放播放

7、DVD;();這樣的語句。privatevoidPlayVideo()DVDdvd=newDVD();();VCDvcd=newVCD();();但是我們在調(diào)要寫很多的類但是我們在調(diào)要寫很多的類上面的代碼可以實現(xiàn)功能但是不好,為什么呢類實現(xiàn)了多態(tài),用的時候并沒有利用多態(tài)。如果我們有很多的影像家電產(chǎn)品,就似F面是使用多態(tài)完成播放功能的代碼:privatevoidPlayVideo()VideoWiringvw;vw=newDVD();Play(vw);vw=newVCD();Play(vw);privatevoidPlay(VideoWiringvw)stringstr=();(str);無論是

8、什么影像家電產(chǎn)品,我們都可以使用一個統(tǒng)一的方式進行播放,即()我們再討論一下,上面的代碼存在的問題。雖然上的代碼很短,應(yīng)該不會有問題,但是我們定位的目標應(yīng)該更高些,應(yīng)該考慮怎樣達到良好的封裝效果,減少錯誤修改的機會。我們自然的應(yīng)該考慮對象創(chuàng)建的問題了,能不能讓不同的影像家電產(chǎn)品的創(chuàng)建方式相同,而且這個創(chuàng)建過程對使用者封裝,也就是說讓對象的創(chuàng)建象播放功能那樣簡單、可擴展性和盡量少的修改量。廠模式,聽說它能夠?qū)崿F(xiàn)”的創(chuàng)建象播放功能那樣簡單、可擴展性和盡量少的修改量。廠模式,聽說它能夠?qū)崿F(xiàn)”統(tǒng)一。如果能夠?qū)崿F(xiàn),會給我們的系統(tǒng)帶來更大的哇!那該多好呀”。不要羨慕了,來看看簡單工簡單工廠模式我們使用簡單

9、工廠對上面的代碼繼續(xù)改進,根據(jù)上面的分析我們考慮對對象創(chuàng)建進行近一步的封裝。使用一個類專門來完成對對象創(chuàng)建的封裝,這個類我們稱為工廠,因為它的作用很單一就生成出一個個的類。下面是一個工廠類的示例代碼:publicclassCreatepublicstaticVideoWiringfactory(stringVideoName)switch(VideoName)caseDVD:returnnewDVD();caseVCD:returnnewVCD();returnnull;這樣我們的客戶端代碼又可以更加有效簡潔了:注意:在上面的兩段代碼示例中我們就已經(jīng)使用了向上轉(zhuǎn)型。首先注意在Create類的f

10、actory方法中使用了returnnewDVD();這樣的語句,但是這個函數(shù)的返回值卻是VideoWiring,它DVD類的基類。所以我們的客戶程序才可以使用VideoWiringvw=(DVD)這樣的語句。這樣客戶程序并不關(guān)心創(chuàng)建是如何完成的,以及創(chuàng)建的對象是什么,我們都可以調(diào)用基類統(tǒng)一的接口實現(xiàn)他們的功能。使用UML表示如下圖所示:privatevoidPlayVideo()VideoWiringvw=(DVD);();vw=(VCD);();DVDCredit+t卸匸亡oWin門q*+PlaVideo:tlnng_-DVDCredit+t卸匸亡oWin門q*+PlaVideo:tlnn

11、g_-vco*ConLret?FrodrjGt角色說明:工廠類(Creator):根據(jù)業(yè)務(wù)邏輯創(chuàng)建具體產(chǎn)品,由客戶程序直接調(diào)用抽象產(chǎn)品(Product):作為具體產(chǎn)品的基類,提供統(tǒng)一的接口,也是工廠類要返回的類型。具體產(chǎn)品(ConcreteProduct):工廠類真正要創(chuàng)建的類型。上圖中僅僅展示了一個具體產(chǎn)品,有多個產(chǎn)品的時候類似。下面我們對簡單工廠模式進行總結(jié)。使用簡單工廠的好處是:1、充分利用了多態(tài)性不管什么具體產(chǎn)品都返回抽象產(chǎn)品。2、充分利用了封裝性,內(nèi)部產(chǎn)品發(fā)生變化時外部使用者不會受到影響。缺點是:如果增加了新的產(chǎn)品,就必須得修改工廠(Factory)抽象工廠模式可以向客戶端提供一個接

12、口,使得客戶端在不必指定產(chǎn)品的具體類型的情況下,創(chuàng)建多個產(chǎn)品族中的產(chǎn)品對象。這就是抽象工廠模式的用意我們將工廠模式推廣到一般的情況,它的類圖如下所示:呼11十1M1.flVCDOVO在有名的00D的設(shè)計原則中有一個叫做里氏代換原則(LiskovSubstitutionPrinciple,LSP)它的實質(zhì)也就是講向上轉(zhuǎn)型。它的內(nèi)容是:任何接收父類型的地方,都應(yīng)當能夠接收子類型,換句話說如果使用的是一個基類的話,那么一定適用于其子類,而且程序察覺不出基類對象和子類對象的區(qū)別。LSP是繼承復(fù)用的基石,只有當派生類可以替換掉基類,軟件的功能不受到影響時,基類才能真正被復(fù)用。工廠方法有了簡單工廠模式后,

13、已經(jīng)給我們帶來了一些好處,但是還存在一些問題,如果我們又多了一個影像家電產(chǎn)品MP4之后,我們可以使MP4類從VideoWiring派生,但是卻要修改Create類的代碼使它能夠生產(chǎn)出MP4這個產(chǎn)品來。不好的地方就在于,我們每次多一個產(chǎn)品的時候都需要修改Create而不是保持原來的代碼不修改僅僅進行一種擴展。在Create類中修改不是每次都簡單的多一個Case語句就能夠解決問題。因為Create類中還封裝了創(chuàng)建對象的邏輯,有可能還需要修改這些邏輯。這就違反了面向?qū)ο笤O(shè)計中一個很重要的原則開-閉”原則。開-閉”原則(theOpenClosedPrincipleOCP:在面向?qū)ο笤O(shè)計中,如何通過很小

14、的設(shè)計改變就可以應(yīng)對設(shè)計需求的變化,這是令設(shè)計者極為關(guān)注的問題。開閉原則就是一個軟件實體在擴展性方面應(yīng)該是開放的而在更改性方面應(yīng)該是封閉的。這個原則說的是,在設(shè)計一個模塊的時候,應(yīng)當使這個模塊可以在不被修改的前提下被擴展。通過擴展已有的軟件系統(tǒng),可以提供新的行為,以滿足對軟件的新需求,使變化中的軟件系統(tǒng)有一定的適應(yīng)性和靈活性。已有的軟件模塊,特別是最重要的抽象層模塊不能再修改,這就使得變化中的軟件系統(tǒng)有一定的穩(wěn)定性和延續(xù)性。因此在進行面向?qū)ο笤O(shè)計時要盡量考慮接口封裝機制、抽象機制和多態(tài)技術(shù)。前邊設(shè)計(簡單工廠)中存在的問題就是它分裝了創(chuàng)建不同對象的邏輯,當有新的產(chǎn)品的時候不易擴展。在開閉原則的

15、指導(dǎo)下我們考慮如何重新修改前邊的設(shè)計,我們要盡量使用抽象機制和多態(tài)技術(shù)。我們放棄對創(chuàng)建不同對象的邏輯的封裝,也采用類似產(chǎn)品的方式,抽象出抽象工廠,具體工廠,具體工廠從抽象工廠派生,每個具體工廠中生產(chǎn)一種具體的產(chǎn)品。太棒了,告訴你,你的這個想法就是工廠方法模式”。F面使用工廠方法模式修改前邊的設(shè)計:VideoWiring、DVD、VCD三個類的代碼和前邊的相同,下面我們看看在客戶端如何使用。publicabstractclassCreatepublicabstractVideoWiringfactory。;publicclassDVDCreate:CreatepublicoverrideVide

16、oWiringfactory。returnnewDVD();publicclassVCDCreate:CreatepublicoverrideVideoWiringfactory()returnnewVCD();MP4的時候如何處理。MP4的時候如何處理。下面我們考慮需要擴展一個新的產(chǎn)品privatevoidPlayVideo()VideoWiringdvd,vcd;CreatedvdCreate,vcdCreate;dvdCreate=newDVDCreate();dvd=();Play(dvd);vcdCreate=newVCDCreate();vcd=();Play(vcd);帕cftj

17、”VideoWlrrng帕cftj”VideoWlrrngDVDCieateVCDCrete-MP4Create-+factoiyVid&oWiring+tacJflrv:VideaWifing1-fl+fadoiyVideoWiring-ITD.DVDVCDhl尸4+Flaj?Video:string+Flaiy/ideostring*FlayVide:Jtring我們來看看增加的代碼:publicclassMP4Create:CreatepublicoverrideVideoWiringfactory。returnnewMP4();publicclassMP4:VideoWiringpub

18、licoverridestringPlayVideo()return正在播放MP4;我們再看看客戶端代碼:MP4的時候沒有修改原來的代碼,而僅僅是對原來的功能進行擴展系統(tǒng)便有了MP4這個產(chǎn)品的功能。privatevoidPlayVideo()VideoWiringdvd,vcd;CreatedvdCreate,vcdCreate;dvdCreate=newDVDCreate();dvd=();Play(dvd);vcdCreate=newVCDCreate();vcd=();Play(vcd);/下面是新增的代碼VideoWiringmp4;Createmp4Create;mp4Create=

19、newMP4Create();mp4=();Play(mp4);我們可以看出使用了工廠方法模式后,很好的滿足了開閉原則,當我們增加了一個新的產(chǎn)品將工廠方法模式推廣到一般情況:=ptnrj7尸詔仃;rcd1Pr.jdijct:.lPjUl.L-nH、:-nH、:m抻iTiwCraatesfrodtucl4wi7W帽科Creator丄打七匚cncrerecrfdiori+ConetelePrcxiuctl+CUlLbr,iyjUxL2角色說明:抽象工廠(Creator):定義具體工廠的接口,所有的創(chuàng)建對象的工廠類都必須實現(xiàn)這些接口。具體工廠(ConcreteCreator):具體工廠包含與應(yīng)用密切

20、相關(guān)的邏輯。復(fù)雜創(chuàng)建具體的產(chǎn)品。抽象產(chǎn)品(Product):所有產(chǎn)品的基類。具體產(chǎn)品(ConcreteProduct):實現(xiàn)抽象產(chǎn)品申明的接口。工廠方法模式所創(chuàng)建的每個對象都是某個具體產(chǎn)品的實例。工廠方法模式的用意是定義一個創(chuàng)建產(chǎn)品對象的工廠接口,將實際創(chuàng)建工作推遲到子類中。工廠方法模式是簡單工廠模式的進一步抽象和推廣。由于使用了多態(tài)性,工廠方法模式保持了簡單工廠模式的優(yōu)點,而且克服了它的缺點。在工廠方法模式中,核心的工廠類不再負責所有的產(chǎn)品的創(chuàng)建,而是將具體創(chuàng)建的工作交給子類去做。這個核心類則成為了一個抽象工廠角色,僅負責給出具體工廠子類必須實現(xiàn)的接口,而不接觸哪一個產(chǎn)品類應(yīng)當被實例化這種細

21、節(jié)。這種進一步抽象化的結(jié)果,使這種工廠方法模式可以用來允許系統(tǒng)在不修改具體工廠角色的情況下引進新的產(chǎn)品。抽象工廠模式我們繼續(xù)對影像家電產(chǎn)品的情形進行分析,我們已經(jīng)可以使用工廠方法比較好的實現(xiàn)了產(chǎn)品的創(chuàng)建,但是在以前的分析中我們并沒有考慮產(chǎn)品種類及生產(chǎn)廠家這樣的問題。就拿DVD來說TCL可以生產(chǎn)、LG也生產(chǎn)等等很多廠家都生產(chǎn)。DVD是產(chǎn)品種類中的一種,產(chǎn)品種類這個概念在有些書上稱為產(chǎn)品族。從另外一個角度來看TCL可以生產(chǎn)DVDVCD等等很多產(chǎn)品,這些產(chǎn)品在一起就可以構(gòu)成一個產(chǎn)品結(jié)構(gòu)。當我們考慮了這些問題后,提出了兩個概念:產(chǎn)品種類、產(chǎn)品結(jié)構(gòu)。我們在工廠方法中討論的是一個個單一的產(chǎn)品的創(chuàng)建,如果我

22、們對這個問題進行進一步的研究、拓展,就應(yīng)該從單一的產(chǎn)品過度到多個產(chǎn)品種類,在工廠方法中我們考慮DVD是一個單一的產(chǎn)品,現(xiàn)在我們認為DVD是一個產(chǎn)品種類,有TCL生產(chǎn)的DVD,有LG生產(chǎn)的DVD,VCD是另一個產(chǎn)品種類,有TCL生產(chǎn)的VCD,有LG生產(chǎn)的VCD就這個問題我們重新分析,有兩個產(chǎn)品種類分別是DVDVCD,有兩個工廠是TCL和LG,它們分別生產(chǎn)DVD和VCD我們使用下面的類圖來表示:DVD是抽象類它提供統(tǒng)一的接口,LGDVDTCLDVD是兩個具體的類。VCD和DVD類似。有一個抽象的工廠Create,從它派生了兩個具體的類TCLCreateLGCreateCreate中提供了兩個抽象方

23、法factoryDVD和factoryVCD它們提供了兩個接口,用于創(chuàng)建DVD產(chǎn)品和VCD產(chǎn)品。在TCLCreateLGCreate中實現(xiàn)這兩個方法。這樣TCLCreate就可以創(chuàng)建自己的DVDVCD,同樣LGCreate也可以傳經(jīng)自己的產(chǎn)品。F面是代碼結(jié)構(gòu):publicabstractclassCreatepublicabstractDVDfactoryDVD();publicabstractVCDfactoryVCD();publicclassLGCreate:CreatepublicoverrideDVDfactoryDVD()returnnewLGDVD();publicoverrid

24、eVCDfactoryVCD()returnnewLGVCD();publicclassTCLCreate:CreatepublicoverrideDVDfactoryDVD()returnnewTCLDVD();publicoverrideVCDfactoryVCD()returnnewTCLVCD();publicabstractclassDVDpublicabstractstringPlayVideo();publicclassLGDVD:DVDpublicoverridestringPlayVideo()returnLG的DVD在播放“publicclassTCLDVD:DVDpubl

25、icoverridestringPlayVideo()returnTCL的DVD正在播放;publicabstractclassVCDpublicabstractstringPlayVideo();publicclassLGVCD:VCDpublicoverridestringPlayVideo()returnLG的VCD正在播放;publicclassTCLVCD:VCDpublicoverridestringPlayVideo()returnTCL的VCD正在播放;客戶端使用抽象工廠代碼如下:privatevoidbutton1_Click(objectsender,e)CreateTCL,LG;TCL=newTCLCreate();LG=newLGCreate();PlayDVD(TCL);/輸岀“TC的DVD在播放”PlayDVD(LG);/輸岀“LG勺DVD在播放”privatevoidPlayDVD(Createcreate)DVDdvd=();();下面將抽象工廠模式推廣到一般情況,它的類圖如下所示:interfaceOa?tor+facioryA:RoductA+fadoryBFroducIBinterfacePiwiuctAConcre(Creator111+factoryA:PrOductAConoreteCreator2+fctoryBProdu

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 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. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論