實戰:基本圖元與複合圖元構建複雜圖形樹
完整代碼實作
using System;
using System.Collections;
// 抽象構件
abstract class DrawingElement
{
protected string name;
public DrawingElement(string name) => this.name = name;
public abstract 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 {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);
}
}
執行結果
- Picture
-- draw a Red Line
-- draw a Blue Circle
-- draw a Green Box
-- + Two Circles
---- draw a Black Circle
---- draw a White Circle
核心優勢展現
- 統一介面:客戶端同樣呼叫
Display(),無需區分葉節點/合成節點
- 遞歸結構:
CompositeElement.Display() 遞歸調用子元素 Display()
- 動態組合:運行時任意增刪子元素,結構靈活變化
- 開閉原則:新增圖元類型只需實作
DrawingElement,不修改既有代碼
與其他模式關聯
- 迭代器模式:遍歷合成結構
- 訪問者模式:對合成結構執行複雜操作
- 裝飾模式:動態為構件添加職責
- 享元模式:共享大量細粒度葉節點