1、定義安全
組合模式:將對象組合成樹形結構以表示「部分-總體」的層次結構。組合模式使得用戶對單個對象和組合對象的使用具備一致性。ide
解釋:簡單來講,編寫一個類,該類能做用於總體,而且編寫總體中的部分時也能使用該類,而不用作大的更改。this
2、UML類圖及基本代碼spa
基本代碼:設計
abstract class Component { protected string name; public Component(string name) { this.name = name; } public abstract void Add(Component component); public abstract void Remove(Component component); public abstract void Display(int depth); } class Leaf : Component { public Leaf(string name) : base(name) { } public override void Add(Component component) { Console.WriteLine("cannot add to a leaf"); } public override void Remove(Component component) { Console.WriteLine("cannot remove to a leaf"); } public override void Display(int depth) { Console.WriteLine(new string('-', depth) + name); } } class Composite : Component { private IList<Component> children = new List<Component>(); public Composite(string name) : base(name) { } public override void Add(Component component) { children.Add(component); } public override void Remove(Component component) { children.Remove(component); } public override void Display(int depth) { Console.WriteLine(new string('-', depth) + name); foreach (Component component in children) { component.Display(depth + 2); } } }
客戶端進行調用:code
Composite root = new Composite("root"); root.Add(new Leaf("leaf A")); root.Add(new Leaf("leaf B")); Composite composite = new Composite("Composite X"); composite.Add(new Leaf("leaf XA")); composite.Add(new Leaf("leaf XB")); root.Add(composite); Composite composite2 = new Composite("Composite XY"); composite2.Add(new Leaf("leaf XYA")); composite2.Add(new Leaf("leaf XYB")); composite.Add(composite2); root.Add(new Leaf("leaf C")); Leaf leaf = new Leaf("Leaf D"); root.Add(leaf); root.Remove(leaf); root.Display(1);
結果如圖:component
3、透明方式和安全方式對象
基本代碼中,leaf類也有add和remove方法,也就是說Component聲明全部用來管理子對象的方法,實現了全部子類都具有其方法的目的。這樣作的好處就是葉節點和枝節點對於外界沒有區別,它們具有徹底一致的行爲接口。但由於leaf不具有add和remove的功能,因此實現它是沒有意義的。這種方式就是透明方式。blog
安全方式是葉節點和枝節點不具備相同的接口,因爲不夠透明,那麼客戶端調用時須要作相應的判斷,帶來了不便。因此在實際項目中使用安全方式和透明方式就須要視狀況而定。接口
4、舉例說明:
繪製一個圖形,該圖形由一個複雜圖形和兩條線段組成。能夠自由的移除該圖形。
public abstract class Graphics { public string Name { get; set; } public Graphics(string name) { this.Name = name; } public abstract void Draw(); public abstract void Add(Graphics graphics); public abstract void Remove(Graphics graphics); } public class Line : Graphics { public Line(string name) : base(name) { } public override void Draw() { Console.WriteLine("畫 " + Name); } public override void Add(Graphics graphics) { throw new Exception("不能向簡單圖形line添加圖形"); } public override void Remove(Graphics graphics) { throw new Exception("不能向簡單圖形line移除圖形"); } } public class Circle : Graphics { public Circle(string name) : base(name) { } public override void Draw() { Console.WriteLine("畫 " + Name); } public override void Add(Graphics g) { throw new Exception("不能向簡單圖形Circle添加其餘圖形"); } public override void Remove(Graphics g) { throw new Exception("不能向簡單圖形Circle移除其餘圖形"); } } public class ComplexGraphics : Graphics { private IList<Graphics> complexGraphicsList = new List<Graphics>(); public ComplexGraphics(string name) : base(name) { } public override void Draw() { foreach (Graphics g in complexGraphicsList) { g.Draw(); } } public override void Add(Graphics graphics) { complexGraphicsList.Add(graphics); } public override void Remove(Graphics graphics) { complexGraphicsList.Remove(graphics); } }
客戶端調用:
ComplexGraphics complexGraphics = new ComplexGraphics("一個複雜圖形和兩條線段組成的複雜圖形"); complexGraphics.Add(new Line("線段A")); ComplexGraphics complexGraphics2 = new ComplexGraphics("一個圓和一條線組成的複雜圖形"); complexGraphics2.Add(new Circle("圓")); complexGraphics2.Add(new Line("線段B")); complexGraphics.Add(complexGraphics2); Line line = new Line("線段C"); complexGraphics.Add(line); Console.WriteLine("複雜圖形的繪製以下:"); Console.WriteLine("----------------------"); complexGraphics.Draw(); Console.WriteLine("複雜圖形的繪製完成"); Console.WriteLine("----------------------"); complexGraphics.Remove(line); Console.WriteLine("移除線段C後,複雜圖形的繪製以下:"); Console.WriteLine("---------------------"); complexGraphics.Draw(); Console.WriteLine("複雜圖形繪製完成"); Console.WriteLine("---------------------");
調用結果:
5、優缺點及適用場景
優勢:
1)組合模式使得客戶端能夠一致的處理對象和對象容器,既是葉節點和枝節點。
2)更容易的爲組合對象添加新的組件。
3)解耦了客戶端與複雜對象。
缺點:
設計更加複雜。
適用場景:
1)須要表示一個對象總體和部分的層次結構
2)用戶但願忽略組合對象和單個對象的不一樣,一致的處理組合對象和單個對象。