1. 程式人生 > >設計模式-結構型-組合模式

設計模式-結構型-組合模式

組合模式(Composite):

定義:

  組合模式又叫部分整體模式,它是一種將物件組合成樹狀的層次結構模式,用來表示"部分-整體"的關係,使使用者對單個物件和組合物件具有一致的訪問性。

組合模式的角色:

  1)抽象構建(Component):它的主要作用是為樹葉構件和樹枝構件宣告公共介面,並實現它們的預設行為。在透明式的組合模式中抽象構件還宣告訪問和管理子類的介面;在安全式的組合模式中不宣告訪問和管理子類的介面,管理工作由樹枝構件完成。

  2)樹葉構件(Leaf):是組合中的葉節點物件,它沒有子節點,用於實現抽象構件角色中 宣告的公共介面。

  3)樹枝構件(Composite):是組合中的分支節點物件,它有子節點。它實現了抽象構件角色中宣告的介面,它的主要作用是儲存和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。

  

 1 internal class Program
 2 {
 3     private static void Main(string[] args)
 4     {
 5         // Create a tree structure
 6         Composite root = new Composite("root");
 7         root.Add(new Leaf("Leaf A"));
 8         root.Add(new Leaf("Leaf B"));
 9 
10         Composite comp = new Composite("Composite X");
11         comp.Add(new Leaf("Leaf XA"));
12         comp.Add(new Leaf("Leaf XB"));
13 
14         root.Add(comp);
15         root.Add(new Leaf("Leaf C"));
16 
17         // Add and remove a leaf
18         Leaf leaf = new Leaf("Leaf D");
19         root.Add(leaf);
20         root.Remove(leaf);
21 
22         // Recursively display tree
23         root.Display(1);
24     }
25 }
26 
27 public abstract class Component
28 {
29     protected string _name;
30 
31     public Component(string name)
32     {
33         this._name = name;
34     }
35 
36     public abstract void Add(Component c);
37 
38     public abstract void Remove(Component c);
39 
40     public abstract void Display(int depth);
41 }
42 
43 public class Leaf : Component
44 {
45     public Leaf(string name)
46         : base(name)
47     {
48     }
49 
50     public override void Add(Component c)
51     {
52         Console.WriteLine("Cannot add to a leaf");
53     }
54 
55     public override void Remove(Component c)
56     {
57         Console.WriteLine("Cannot remove from a leaf");
58     }
59 
60     public override void Display(int depth)
61     {
62         Console.WriteLine(new String('-', depth) + _name);
63     }
64 }
65 
66 public class Composite : Component
67 {
68     private List<Component> _children = new List<Component>();
69 
70     public Composite(string name)
71         : base(name)
72     {
73     }
74 
75     public override void Add(Component component)
76     {
77         _children.Add(component);
78     }
79 
80     public override void Remove(Component component)
81     {
82         _children.Remove(component);
83     }
84 
85     public override void Display(int depth)
86     {
87         Console.WriteLine(new String('-', depth) + _name);
88 
89         foreach (Component component in _children)
90         {
91             component.Display(depth + 2);
92         }
93     }
94 }

 極簡版如下,將顯示部分可以拿到客戶端進行:

 1 internal class Program
 2 {
 3     private static void Main(string[] args)
 4     {
 5         // Create a tree structure
 6         Component root = new Component("root");
 7         root.Add(new Component("Leaf A"));
 8         root.Add(new Component("Leaf B"));
 9 
10         Component comp = new Component("Composite X");
11         comp.Add(new Component("Leaf XA"));
12         comp.Add(new Component("Leaf XB"));
13 
14         root.Add(comp);
15         root.Add(new Component("Leaf C"));
16 
17         // Add and remove a leaf
18         Component leaf = new Component("Leaf D");
19         root.Add(leaf);
20         root.Remove(leaf);
21 
22         // 由客戶端顯示,Component只進行組合
23     }
24 }
25 
26 public class Component
27 {
28     protected string _name;
29     private List<Component> _children = new List<Component>();
30 
31     public Component(string name)
32     {
33         this._name = name;
34     }
35 
36     public void Add(Component c)
37     {
38         _children.Add(c);
39     }
40 
41     public void Remove(Component c)
42     {
43         _children.Remove(c);
44     }
45 
46     public List<Component> GetChild()
47     {
48         return _children;
49     }
50 }

是不是恍然大悟,就是我們在做許可權管理的時候用到的一對多的關係。

組合模式的優缺點:

  優點:

    1)組合模式使得客戶端程式碼可以一致地處理單個物件和組合物件,無須關心自己處理的單個物件還是組合物件,這簡化了客戶端程式碼;

    2)更容易在組合體內加入新的物件,客戶端不會因為加入新的物件而更改原始碼,滿足OCP原則。

  缺點:

    1)設計較複雜,客戶端需要花更多的時間理清類之間的層次關係;

    2)不容易限制容器中的構件;

    3)不容易用繼承的方法來增加構件的新功能。

參考:https://www.cnblogs.com/libingql/p/3496345.