剖析設計模式編程中C#對于組合模式的運用
一、引言
在軟件開發(fā)過程中,我們經(jīng)常會遇到處理簡單對象和復合對象的情況,例如對操作系統(tǒng)中目錄的處理就是這樣的一個例子,因為目錄可以包括單獨的文件,也可以包括文件夾,文件夾又是由文件組成的,由于簡單對象和復合對象在功能上區(qū)別,導致在操作過程中必須區(qū)分簡單對象和復合對象,這樣就會導致客戶調(diào)用帶來不必要的麻煩,然而作為客戶,它們希望能夠始終一致地對待簡單對象和復合對象。然而組合模式就是解決這樣的問題。下面讓我們看看組合模式是怎樣解決這個問題的。
二、組合模式的詳細介紹
2.1 組合模式的定義
組合模式允許你將對象組合成樹形結(jié)構(gòu)來表現(xiàn)”部分-整體“的層次結(jié)構(gòu),使得客戶以一致的方式處理單個對象以及對象的組合。下面我們用繪制的例子來詳細介紹組合模式,圖形可以由一些基本圖形元素組成(如直線,圓等),也可以由一些復雜圖形組成(由基本圖形元素組合而成),為了使客戶對基本圖形和復雜圖形的調(diào)用保持一致,我們使用組合模式來達到整個目的。
組合模式實現(xiàn)的最關鍵的地方是——簡單對象和復合對象必須實現(xiàn)相同的接口。這就是組合模式能夠?qū)⒔M合對象和簡單對象進行一致處理的原因。
2.2 組合模式的實現(xiàn)
舉例:
家族譜的編寫:
男性:可傳宗接代,也有權(quán)利把一些人剔除族譜。
女性:記錄到家譜中,但不能傳宗接代。
理解:每一個小家庭中,爸爸媽媽和我,都是爸爸做主,可踢出我跟媽媽中的任何一個,也可增加任何一個。組件模式中的組件可以是單獨一個對象組成,也可以是多個組件組成(一個家庭,甚至一個家庭的多級延續(xù));
類圖:
族員共性代碼:
//// <summary> /// //族人 抽象出來的族人共性 /// </summary> public abstract class Father { //族人的姓名 protected string name = string.Empty; public string Name { get { return name; } } //增加后代 public abstract void Add(Father boy); //逐出家譜 public abstract void Remove(Father boy); //定義所有族人,做個簡介 public abstract void Intro(); }家族成員代碼 //男性后代 public class Boy : Father { //構(gòu)造函數(shù) public Boy() { } public Boy(string Name) { this.name = Name; } List<Father> myFamily = new List<Father>(); //自我簡介 public override void Intro() { Console.WriteLine("我是:{0};", Name); foreach (Father f in myFamily) { f.Intro(); } } //增加后代 public override void Add(Father boy) { myFamily.Add(boy); } //逐出家譜 public override void Remove(Father boy) { myFamily.Remove(boy); } } //女性后代 public class Gril : Father { //構(gòu)造函數(shù) public Gril() { } public Gril(string Name) { this.name = Name; } //自我簡介 public override void Intro() { Console.WriteLine("我是:{0};", Name); } //不能添加 public override void Add(Father store) { throw new NotImplementedException(); } //不能刪除 public override void Remove(Father store) { throw new NotImplementedException(); } }客戶端代碼: public static void Main() { //爺爺取老婆 Boy yeye = new Boy("爺爺"); Gril nainai = new Gril("奶奶"); yeye.Add(nainai); //爺爺要孩子 Boy baba = new Boy("爸爸"); Gril gugu = new Gril("姑姑"); yeye.Add(gugu); yeye.Add(baba); //爸爸要我 Boy me = new Boy("me"); baba.Add(me); //我要孩子 Boy son = new Boy("son"); me.Add(son); //爺爺?shù)拇蠹彝?,族譜做介紹 yeye.Intro(); Console.Read(); }
2.3組合模式的類圖
看完了上面,讓我們具體看看組合模式的類圖來理清楚組合模式中類之間的關系。
透明式的組合模式類圖:
安全式組合模式的類圖:
組合模式中涉及到三個角色:
- 抽象構(gòu)件(Component)角色:這是一個抽象角色,上面實現(xiàn)中Graphics充當這個角色,它給參加組合的對象定義出了公共的接口及默認行為,可以用來管理所有的子對象(在透明式的組合模式是這樣的)。在安全式的組合模式里,構(gòu)件角色并不定義出管理子對象的方法,這一定義由樹枝結(jié)構(gòu)對象給出。
- 樹葉構(gòu)件(Leaf)角色:樹葉對象時沒有下級子對象的對象,上面實現(xiàn)中Line和Circle充當這個角色,定義出參加組合的原始對象的行為
- 樹枝構(gòu)件(Composite)角色:代表參加組合的有下級子對象的對象,上面實現(xiàn)中ComplexGraphics充當這個角色,樹枝對象給出所有管理子對象的方法實現(xiàn),如Add、Remove等。
三、組合模式的優(yōu)缺點
優(yōu)點:
組合模式使得客戶端代碼可以一致地處理對象和對象容器,無需關系處理的單個對象,還是組合的對象容器。
將”客戶代碼與復雜的對象容器結(jié)構(gòu)“解耦。
可以更容易地往組合對象中加入新的構(gòu)件。
缺點:使得設計更加復雜。客戶端需要花更多時間理清類之間的層次關系。(這個是幾乎所有設計模式所面臨的問題)。
注意的問題:
有時候系統(tǒng)需要遍歷一個樹枝結(jié)構(gòu)的子構(gòu)件很多次,這時候可以考慮把遍歷子構(gòu)件的結(jié)構(gòu)存儲在父構(gòu)件里面作為緩存。
客戶端盡量不要直接調(diào)用樹葉類中的方法(在我上面實現(xiàn)就是這樣的,創(chuàng)建的是一個樹枝的具體對象,應該使用GraphicscomplexGraphics = new ComplexGraphics("一個復雜圖形和兩條線段組成的復雜圖形");),而是借用其父類(Graphics)的多態(tài)性完成調(diào)用,這樣可以增加代碼的復用性。
四、組合模式的使用場景
在以下情況下應該考慮使用組合模式:
- 需要表示一個對象整體或部分的層次結(jié)構(gòu)。
- 希望用戶忽略組合對象與單個對象的不同,用戶將統(tǒng)一地使用組合結(jié)構(gòu)中的所有對象。
五、組合模式在.NET中的應用
組合模式在.NET 中最典型的應用就是應用與WinForms和Web的開發(fā)中,在.NET類庫中,都為這兩個平臺提供了很多現(xiàn)有的控件,然而System.Windows.Forms.dll中System.Windows.Forms.Control類就應用了組合模式,因為控件包括Label、TextBox等這樣的簡單控件,同時也包括GroupBox、DataGrid這樣復合的控件,每個控件都需要調(diào)用OnPaint方法來進行控件顯示,為了表示這種對象之間整體與部分的層次結(jié)構(gòu),微軟把Control類的實現(xiàn)應用了組合模式(確切地說應用了透明式的組合模式)。
六、總結(jié)
到這里組合模式的介紹就結(jié)束了,組合模式解耦了客戶程序與復雜元素內(nèi)部結(jié)構(gòu),從而使客戶程序可以向處理簡單元素一樣來處理復雜元素。
上一篇:基于C#實現(xiàn)手機號碼歸屬地接口調(diào)用
欄 目:C#教程
下一篇:C#委托與事件初探
本文標題:剖析設計模式編程中C#對于組合模式的運用
本文地址:http://mengdiqiu.com.cn/a1/C_jiaocheng/6691.html
您可能感興趣的文章
- 01-10C#編程實現(xiàn)自定義熱鍵的方法
- 01-10C#編程獲取資源文件中圖片的方法
- 01-10深入淺出23種設計模式
- 01-10C#編程自學之數(shù)據(jù)類型和變量二
- 01-10C#編程自學之開篇介紹
- 01-10C#編程自學之數(shù)據(jù)類型和變量三
- 01-10C#編程自學之運算符和表達式
- 01-10C#編程自學之類和對象
- 01-10C#編程和Visual Studio使用技巧(下)
- 01-10C#編程自學之數(shù)據(jù)類型和變量一


閱讀排行
本欄相關
- 01-10C#通過反射獲取當前工程中所有窗體并
- 01-10關于ASP網(wǎng)頁無法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實現(xiàn)txt定位指定行完整實例
- 01-10WinForm實現(xiàn)仿視頻 器左下角滾動新
- 01-10C#停止線程的方法
- 01-10C#實現(xiàn)清空回收站的方法
- 01-10C#通過重寫Panel改變邊框顏色與寬度的
- 01-10C#實現(xiàn)讀取注冊表監(jiān)控當前操作系統(tǒng)已
隨機閱讀
- 01-10delphi制作wav文件的方法
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-10SublimeText編譯C開發(fā)環(huán)境設置
- 01-11ajax實現(xiàn)頁面的局部加載
- 01-10C#中split用法實例總結(jié)
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 04-02jquery與jsp,用jquery
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-10使用C語言求解撲克牌的順子及n個骰子