2.4.1 模式意圖:
在處理樹形結構數據時,通常必須區分葉節點和分支節點。這使代碼更復雜,也更容易出錯。組合模式模糊了葉節點和分支節點的概念,可以使葉節點和分支節點以單一對象的方式統一處理,且所有節點對象均具有相似的功能。
2.4.2 模式概念:
它屬于結構型模式,將對象組合成樹形結構以表示“部分-整體”的層次結構。組合模式使得用戶對單個對象和組合對象的使用具有一致性。
2.4.3 模式元素:
- 節點抽象(CompsiteBase)
- 葉子節點(Leaf)
- 復合節點(Composite)
2.4.4 代碼示例:
示例相對簡單,就是一個樹狀的結構,一個主干,然后就是分支,每個分支可能是葉子節點,也可能是含有子分支的節點。
A.創建一個節點的抽象基類 ,也就是每個節點基類
public abstract class CompsiteBase
{
protected string name;
public CompsiteBase(string name)
{
this.name = name;
}
public abstract void Add(CompsiteBase c);
public abstract void Remove(CompsiteBase c);
public abstract void Display(int depth);
}
B.葉子節點,也就是不含子節點的分支
public class Leaf : CompositeBase
{
public Leaf(string name) : base(name) { }
public override void Add(CompositeBase c)
{
Debug.Log("Cannot add to a leaf");
}
public override void Remove(CompositeBase c)
{
Debug.Log("Cannot remove from a leaf");
}
public override void Display(int depth)
{
Debug.Log(new string('-', depth) + name);
}
}
C.含有子節點的分支
public class Composite : CompositeBase
{
private List<CompsiteBase> children = new List<CompsiteBase>();
public Composite(string name) : base(name) { }
public override void Add(CompositeBase c)
{
children.Add(c);
}
public override void Remove(CompositeBase c)
{
children.Remove(c);
}
public override void Display(int depth)
{
Debug.Log(new String('-', depth) + name);
foreach (CompositeBase composite in children)
{
compsite.Display(depth + 2);
}
}
}
示例調用
void Start()
{
Composite root = new Composite("root");
root.Add(new Leaf("Leaf A"));
root.Add(new Leaf("Leaf B"));
Composite comp = new Composite("Composite X");
comp.Add(new Leaf("Leaf XA"));
comp.Add(new Leaf("Leaf XB"));
root.Add(comp);
Composite comp2 = new Composite("Composite XY");
comp2.Add(new Leaf("Leaf XYA"));
comp2.Add(new Leaf("Leaf XYB"));
comp.Add(comp2);
root.Add(new Leaf("Leaf C"));
Leaf leaf = new Leaf("Leaf D");
root.Add(leaf);
root.Remove(leaf);
root.Display(1);
}
2.4.5 寫法對比:
略
2.4.6 模式分析:
通過
CompositeBase
接口來統一處理Leaf
和Composite
對象:Leaf
對象直接執行請求,而Composite
對象將請求以遞歸的方式向下傳遞到樹結構的子節點。這使得類更易于實現、更改、測試和重用。
組合模式也分為安全模式和透明模式
- 安全模式:在抽象基類中沒有提供
Add
Remove
等管理子節點的函數。
優點:不必實現不需要的相關函數。
缺點:需要區分葉子節點和含有子節點的分支,進行分別調用。- 透明模式:與安全模式相反,含有對應管理子節點的函數。
優點:可以統一的調用。
缺點:容易錯誤調用相關的管理函數而引發異常。
2.4.7 應用場景:
- 整體部分的層次為樹結構,且需要統一對待部分和整體對象。
2.4.8 小結:
當你發現需求是體現部分與整體層次結構時,以及你希望用戶可以忽律組合對象與單個對象的不同,統一地使用組合結構中的所有對象,就可以考慮使用組合模式了。