組合模式又稱部分-整體模式,將對象組織成樹結構描述整體與部分關係,使客戶端能統一對待單個對象(葉子)與組合對象(樹枝)。如奶奶講的遞歸和尚故事:山裡有廟,廟裡有和尚講故事,故事裡又有山、廟、和尚……角色分為「無子角色」與「含子角色」兩類。

Composite 可包含 Leaf 或其他 Composite,形成遞歸結構。
在 Component 中聲明所有子對象管理方法。優點:客戶端統一介面;缺點:葉子類執行無意義方法(如 Add)僅在運行時報錯。
管理方法僅在 Composite 中聲明。優點:編譯期捕獲錯誤;缺點:葉子與樹枝介面不一致,失去透明性。
// Composite pattern -- Structural example (Safe)
using System; using System.Text; using System.Collections;
abstract class Component {
protected string name;
public Component(string name) { this.name = name; }
public abstract void Display(int depth);
}
class Composite : Component {
private ArrayList children = new ArrayList();
public Composite(string name) : base(name) {}
public void Add(Component c) { children.Add(c); }
public void Remove(Component c) { children.Remove(c); }
public override void Display(int depth) {
Console.WriteLine(new String('-', depth) + name);
foreach (Component c in children) c.Display(depth + 2);
}
}
class Leaf : Component {
public Leaf(string name) : base(name) {}
public override void Display(int depth) { Console.WriteLine(new String('-', depth) + name); }
}
public class Client {
public static void Main() {
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); root.Add(new Leaf("Leaf C"));
Leaf l = new Leaf("Leaf D"); root.Add(l); root.Remove(l);
root.Display(1);
}
}
// Composite pattern -- Structural example (Transparent)
abstract class Component {
protected string name;
public Component(string name) { this.name = name; }
abstract public void Add(Component c);
abstract public void Remove(Component c);
abstract public void Display(int depth);
}
class Composite : Component {
private ArrayList children = new ArrayList();
public Composite(string name) : base(name) {}
public override void Add(Component c) { children.Add(c); }
public override void Remove(Component c) { children.Remove(c); }
public override void Display(int depth) {
Console.WriteLine(new String('-', depth) + name);
foreach (Component c in children) c.Display(depth + 2);
}
}
class Leaf : Component {
public Leaf(string name) : base(name) {}
public override void Add(Component c) { Console.WriteLine("Cannot add to a leaf"); }
public override void Remove(Component c) { Console.WriteLine("Cannot remove from a leaf"); }
public override void Display(int depth) { Console.WriteLine(new String('-', depth) + name); }
}
關鍵設計決策:
// Composite pattern -- Real World example
using System; using System.Collections;
abstract class DrawingElement {
protected string name;
public DrawingElement(string name) { this.name = name; }
abstract public void Display(int indent);
}
class PrimitiveElement : DrawingElement {
public PrimitiveElement(string name) : base(name) {}
public override void Display(int indent) {
Console.WriteLine(new String('-', indent) + " draw a {0}", name);
}
}
class CompositeElement : DrawingElement {
private ArrayList elements = new ArrayList();
public CompositeElement(string name) : base(name) {}
public void Add(DrawingElement d) { elements.Add(d); }
public void Remove(DrawingElement d) { elements.Remove(d); }
public override void Display(int indent) {
Console.WriteLine(new String('-', indent) + "+ " + name);
foreach (DrawingElement c in elements) c.Display(indent + 2);
}
}
public class CompositeApp {
public static void Main() {
CompositeElement root = new CompositeElement("Picture");
root.Add(new PrimitiveElement("Red Line"));
root.Add(new PrimitiveElement("Blue Circle"));
root.Add(new PrimitiveElement("Green Box"));
CompositeElement comp = new CompositeElement("Two Circles");
comp.Add(new PrimitiveElement("Black Circle"));
comp.Add(new PrimitiveElement("White Circle"));
root.Add(comp);
PrimitiveElement l = new PrimitiveElement("Yellow Line");
root.Add(l); root.Remove(l);
root.Display(1);
}
}
輸出呈現清晰的樹形圖形結構,展現組合模式處理遞歸圖形的優雅性。