首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 設計模式精講:組合模式

     編輯:關於C#

一、組合模式:樹形結構的統一治理

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

二、核心角色與兩種實現形式

組合模式結構圖

  1. 抽象構件角色:定義參與組合對象的共同介面與默認行為。
  2. 葉子構件角色:無子對象,定義原始對象行為。
  3. 樹枝構件角色:有子對象,提供子對象管理方法。

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); }
}

五、實戰考量與應用

關鍵設計決策:

  • 子對象保存父引用 → 易於向上遍歷、應用責任鏈模式。
  • 需共享構件時,因父引用存在,享元模式難直接應用。
  • 頻繁遍歷子樹可考慮在父節點緩存遍歷結果。
  • 子對象集合類型視具體場景選擇:ArrayList、List、陣列等。
  • 客戶端盡量面向 Component 多態調用,勿直接調用 Leaf 具體方法。

六、實戰案例:圖形繪製系統

// 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);
    }
}

輸出呈現清晰的樹形圖形結構,展現組合模式處理遞歸圖形的優雅性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved