23種設(shè)計模式匯總結(jié)構(gòu)型模式-組合模式_第1頁
23種設(shè)計模式匯總結(jié)構(gòu)型模式-組合模式_第2頁
23種設(shè)計模式匯總結(jié)構(gòu)型模式-組合模式_第3頁
23種設(shè)計模式匯總結(jié)構(gòu)型模式-組合模式_第4頁
23種設(shè)計模式匯總結(jié)構(gòu)型模式-組合模式_第5頁
已閱讀5頁,還剩7頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、組合模式概述組合模式有時候又叫做部分-整體模式,它使我們樹型結(jié)構(gòu)的問題中,模糊了簡單元素和復(fù)雜元素的概念,客戶程序可以向處理簡單元素一樣來處理復(fù)雜元素,從而使得客戶程序與復(fù)雜元素的內(nèi)部結(jié)構(gòu)解耦。意圖將對象組合成樹形結(jié)構(gòu)以表示部分-整體”的層次結(jié)構(gòu)oComposite模式使得用戶對單個對象和組合對象的使用具有一致性。GOF設(shè)計模式結(jié)構(gòu)圖fcwaachchildinchildrnchild.圖1Composite模式結(jié)構(gòu)圖生活中的例子組合模式將對象組合成樹形結(jié)構(gòu)以表示部分-整體的層次結(jié)構(gòu)。讓用戶一致地使用單個對象和組合對象。雖然例子抽象一些,但是算術(shù)表達式確實是組合的例子。算術(shù)表達式包括操作數(shù)、操

2、作符和另一個操作數(shù)。操作數(shù)可以是數(shù)字,也可以是另一個表達式。這樣,2+3和(2+3)+(4*6)都是合法的表達式。葺術(shù)趙式ooooO圖2使用算術(shù)表達式例子的Composite模式對象圖組合模式解說這里我們用繪圖這個例子來說明Composite模式,通過一些基本圖像元素(直線、圓等)以及一些復(fù)合圖像元素(由基本圖像元素組合而成)構(gòu)建復(fù)雜的圖形樹。在設(shè)計中我們對每一個對象都配備一個Draw()方法,在調(diào)用時,會顯示相關(guān)的圖形??梢钥吹剑@里復(fù)合圖像元素它在充當(dāng)對象的同時,又是那些基本圖像元素的一個容器。先看一下基本的類結(jié)構(gòu)圖:圖3圖中橙色的區(qū)域表示的是復(fù)合圖像元素。示意性代碼:publicabst

3、ractclassGraphicsprotectedstring_name;publicGraphics(stringname)this._name=name;publicabstractvoidDraw();publicclassPicture:GraphicspublicPicture(stringname):base(name)publicoverridevoidDraw()/publicArrayListGetChilds()/返回所有的子對象而其他作為樹枝構(gòu)件,實現(xiàn)代碼如下:publicclassLine:GraphicspublicLine(stringname):base(nam

4、e)publicoverridevoidDraw()Console.WriteLine(Drawa+_name.ToString();publicclassCircle:GraphicspublicCircle(stringname):base(name)publicoverridevoidDraw()Console.WriteLine(Drawa+_name.ToString();publicclassRectangle:GraphicspublicRectangle(stringname):base(name)publicoverridevoidDraw()Console.WriteLin

5、e(Drawa+_name.ToString();現(xiàn)在我們要對該圖像元素進行處理:在客戶端程序中,需要判斷返回對象的具體類型到底是基本圖像元素,還是復(fù)合圖像元素。如果是復(fù)合圖像元素,我們將要用遞歸去處理,然而這種處理的結(jié)果卻增加了客戶端程序與復(fù)雜圖像元素內(nèi)部結(jié)構(gòu)之間的依賴,那么我們?nèi)绾稳ソ怦钸@種關(guān)系呢?我們希望的是客戶程序可以像處理基本圖像元素一樣來處理復(fù)合圖像元素,這就要引入Composite模式了,需要把對于子對象的管理工作交給復(fù)合圖像元素,為了進行子對象的管理,它必須提供必要的Add(),Remove()等方法,類結(jié)構(gòu)圖如下::陽訶MdrfU:vnidIKEntivt():voidI曲-

6、心il也山:FictvrGr&pAicsI0:void刑血A;啊死:uoii;ri:iiiil-1.11.:iM仝令乞+甘閃譏:弟+Add(I;viid沁0心:voidetCh:;小川:少:勺Circle+胡的:戦*+k&niD-Me)1voidJ-圖4示意性代碼:publicabstractclassGraphicsprotectedstring_name;publicGraphics(stringname)this._name=name;publicabstractvoidDraw();publicabstractvoidAdd();publicabstractvoidRemove();p

7、ublicclassPicture:GraphicsprotectedArrayListpicList=newArrayList();publicPicture(stringname):base(name)publicoverridevoidDraw()Console.WriteLine(Drawa+_name.ToString();foreach(GraphicsginpicList)g.Draw();publicoverridevoidAdd(Graphicsg)picList.Add(g);publicoverridevoidRemove(Graphicsg)picList.Remove

8、(g);publicclassLine:GraphicspublicLine(stringname):base(name)publicoverridevoidDraw()Console.WriteLine(Drawa+_name.ToString();publicoverridevoidAdd(Graphicsg)publicoverridevoidRemove(Graphicsg)publicclassCircle:GraphicspublicCircle(stringname):base(name)publicoverridevoidDraw()Console.WriteLine(Draw

9、a+_name.ToString();publicoverridevoidAdd(Graphicsg)publicoverridevoidRemove(Graphicsg)publicclassRectangle:GraphicspublicRectangle(stringname):base(name)publicoverridevoidDraw()Console.WriteLine(Drawa+_name.ToString();publicoverridevoidAdd(Graphicsg)publicoverridevoidRemove(Graphicsg)這樣引入Composite模式

10、后,客戶端程序不再依賴于復(fù)合圖像元素的內(nèi)部實現(xiàn)了。然而,我們程序中仍然存在著問題,因為Line,Rectangle.Circle已經(jīng)沒有了子對象,它是一個基本圖像元素,因此Add(),Remove()的方法對于它來說沒有任何意義,而且把這種錯誤不會在編譯的時候報錯,把錯誤放在了運行期,我們希望能夠捕獲到這類錯誤,并加以處理,稍微改進一下我們的程序:publicclassLine:GraphicspublicLine(stringname):base(name)publicoverridevoidDraw()Console.WriteLine(Drawa+_name.ToString();pub

11、licoverridevoidAdd(Graphicsg)/拋出一個我們自定義的異常publicoverridevoidRemove(Graphicsg)/拋出一個我們自定義的異常這樣改進以后,我們可以捕獲可能出現(xiàn)的錯誤,做進一步的處理。上面的這種實現(xiàn)方法屬于透明式的Composite模式,如果我們想要更安全的一種做法,就需要把管理子對象的方法聲明在樹枝構(gòu)件Picture類里面,這樣如果葉子節(jié)點Line,Rectangle,Circle使用這些方法時,在編譯期就會出錯,看一下類結(jié)構(gòu)圖:圖5示意性代碼:publicabstractclassGraphicsprotectedstring_name

12、;publicGraphics(stringname)this._name=name;publicabstractvoidDraw();publicclassPicture:GraphicsprotectedArrayListpicList=newArrayList();publicPicture(stringname):base(name)publicoverridevoidDraw()Console.WriteLine(Drawa+_name.ToString();foreach(GraphicsginpicList)g.Draw();publicvoidAdd(Graphicsg)pic

13、List.Add(g);publicvoidRemove(Graphicsg)picList.Remove(g);publicclassLine:GraphicspublicLine(stringname):base(name)publicoverridevoidDraw()Console.WriteLine(Drawa+_name.ToString();publicclassCircle:GraphicspublicCircle(stringname):base(name)publicoverridevoidDraw()Console.WriteLine(Drawa+_name.ToStri

14、ng();publicclassRectangle:GraphicspublicRectangle(stringname):base(name)publicoverridevoidDraw()Console.WriteLine(Drawa+_name.ToString();這種方式屬于安全式的Composite模式,在這種方式下,雖然避免了前面所討論的錯誤,但是它也使得葉子節(jié)點和樹枝構(gòu)件具有不一樣的接口。這種方式和透明式的Composite各有優(yōu)劣,具體使用哪一個,需要根據(jù)問題的實際情況而定。通過Composite模式,客戶程序在調(diào)用Draw()的時候不用再去判斷復(fù)雜圖像元素中的子對象到底是基

15、本圖像元素,還是復(fù)雜圖像元素,看一下簡單的客戶端調(diào)用:publicclassApppublicstaticvoidMain()Pictureroot=newPicture(Root);root.Add(newLine(Line);root.Add(newCircle(Circle);Rectangler=newRectangle(Rectangle);root.Add(r);root.Draw();NET中的組合模式如果有人用過EnterpriseLibrary2.0,定在源程序中看到了一個叫做ObjectBuilder的程序集,顧名思義,它是用來負責(zé)對象的創(chuàng)建工作的,而在ObjectBuil

16、der中,有一個被稱為定位器的東西,通過定位器,可以很容易的找到對象,它的結(jié)構(gòu)采用鏈表結(jié)構(gòu),每一個節(jié)點是一個鍵值對,用來標(biāo)識對象的唯一性,使得對象不會被重復(fù)創(chuàng)建。定位器的鏈表結(jié)構(gòu)采用可枚舉的接口類來實現(xiàn),這樣我們可以通過一個迭代器來遍歷這個鏈表。同時多個定位器也被串成一個鏈表。具體地說就是多個定位器組成一個鏈表,表中的每一個節(jié)點是一個定位器,定位器本身又是一個鏈表,表中保存著多個由鍵值對組成的對象的節(jié)點。所以這是一個典型的Composite模式的例子,來看它的結(jié)構(gòu)圖:圖6正如我們在圖中所看到的,IReadableLocator定義了最上層的定位器接口方法,它基本上具備了定位器的大部分功能。部分

17、代碼:publicinterfaceIReadableLocator:IEnumerableKeyValuePair/返回定位器中節(jié)點的數(shù)量intCountget;/一個指向父節(jié)點的引用IReadableLocatorParentLocatorget;/表示定位器是否只讀boolReadOnlyget;/查詢定位器中是否已經(jīng)存在指定鍵值的對象boolContains(objectkey);/查詢定位器中是否已經(jīng)存在指定鍵值的對象,根據(jù)給出的搜索選項,表示是否要向上回溯繼續(xù)尋找。boolContains(objectkey,SearchModeoptions);/使用謂詞操作來查找包含給定對象的

18、定位器IReadableLocatorFindBy(PredicateKeyValuePairpredicate);/根據(jù)是否回溯的選項,使用謂詞操作來查找包含對象的定位器IReadableLocatorFindBy(SearchModeoptions,PredicateKeyValuePairpredicate);/從定位器中獲取一個指定類型的對象TItemGet();/從定位其中獲取一個指定鍵值的對象TItemGet(objectkey);/根據(jù)選項條件,從定位其中獲取一個指定類型的對象TItemGet(objectkey,SearchModeoptions);/給定對象鍵值獲取對象的非泛

19、型重載方法objectGet(objectkey);/給定對象鍵值帶搜索條件的非泛型重載方法objectGet(objectkey,SearchModeoptions);一個抽象基類ReadableLocator用來實現(xiàn)這個接口的公共方法。兩個主要的方法實現(xiàn)代碼如下:publicabstractclassReadableLocator:IReadableLocator/*/查找定位器,最后返回一個只讀定位器的實例/publicIReadableLocatorFindBy(SearchModeoptions,PredicateKeyValuePairpredicate)if(predicate=

20、null)thrownewArgumentNullException(predicate);if(!Enum.IsDefined(typeof(SearchMode),options)thrownewArgumentException(Properties.Resources.InvalidEnumerationValue,options);Locatorresults=newLocator();IReadableLocatorcurrentLocator=this;while(currentLocator!=null)FindInLocator(predicate,results,curre

21、ntLocator);currentLocator=options=SearchMode.Local?null:currentLocator.ParentLocator;returnnewReadOnlyLocator(results);/*/遍歷定位器/privatevoidFindInLocator(PredicateKeyValuePairpredicate,Locatorresults,IReadableLocatorcurrentLocator)foreach(KeyValuePairkvpincurrentLocator)if(!results.Contains(kvp.Key)&

22、predicate(kvp)results.Add(kvp.Key,kvp.Value);可以看到,在FindBy方法里面,循環(huán)調(diào)用了FindlnLocator方法,如果查詢選項是只查找當(dāng)前定位器,那么循環(huán)終止,否則沿著定位器的父定位器繼續(xù)向上查找。FindlnLocator方法就是遍歷定位器,然后把找到的對象存入一個臨時的定位器。最后返回一個只讀定位器的新的實例。從這個抽象基類中派生出一個具體類和一個抽象類,一個具體類是只讀定位器(ReadOn“Locator),只讀定位器實現(xiàn)抽象基類沒有實現(xiàn)的方法,它封裝了一個實現(xiàn)了IReadableLocator接口的定位器,然后屏蔽內(nèi)部定位器的寫入接口方法。另一個繼承的是讀寫定位器抽象類ReadWriteLocator,為了實現(xiàn)對定位器的寫入和刪除,這里定義了一個對IReadableLocator接口擴展的接口叫做IReadWriteLocator,在這個接口里面提供了實現(xiàn)定位器的操作:圖7實現(xiàn)代碼如下:publicinterfaceIReadWriteLocator:IReadableLocator/保存對象到定位器voidAdd(objectkey,objectvalue);/從定位器中刪除一個對象,如果成功返

溫馨提示

  • 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)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論