本章介紹 COMPOSITE 模式——一種將物件組合成樹狀結構,使客戶端能以一致的方式處理單一物件與物件集合的設計模式。

意圖與動機#

  • 很多系統中存在「一個命令」與「一組命令」的區別,客戶端需要用不同的方式處理它們
  • COMPOSITE 模式的核心思想:讓「一」與「多」看起來相同——客戶端不需要知道它操作的是單一物件還是物件的組合

Figure 31.1: COMPOSITE pattern

  • 結構上,CompositeLeaf 都實作相同的介面(Component
  • Composite 持有一個 Component 的集合,其 operation() 方法會遍歷所有子元素並依次呼叫它們的 operation()

範例:CompositeCommand#

Figure 31.2: Sensor containing many Commands

  • 在感應器(Sensor)系統中,一個感應器觸發時可能需要執行多個 Command
  • 沒有 COMPOSITE 之前:Sensor 持有一個 List<Command>,並在觸發時逐一呼叫
  • 套用 COMPOSITE 之後:建立一個 CompositeCommand,它本身也實作 Command 介面
public class CompositeCommand : Command
{
    private List<Command> commands = new List<Command>();

    public void Add(Command command)
    {
        commands.Add(command);
    }

    public void Execute()
    {
        foreach (Command command in commands)
            command.Execute();
    }
}
  • 現在 Sensor 只持有一個 Command 參考——它可能是單一命令,也可能是 CompositeCommand
  • 一對多的關係被簡化為一對一,大幅降低了 Sensor 的複雜度

技巧: COMPOSITE 模式的威力在於消除了條件邏輯——客戶端不需要用 ifinstanceof 來判斷處理的是單一物件還是集合,因為兩者的介面完全相同。

多重性而非集合#

  • 使用 COMPOSITE 後,容器類別不需要知道「裡面可能有多個」的概念
  • 如果只有一個命令,直接持有該命令即可;如果需要多個,包裝成 CompositeCommand
  • 這就是所謂的多重性簡化:將 1:* 關係轉化為 1:1 關係

重點: COMPOSITE 模式不只是一種資料結構技巧——它代表了一種思維方式的轉變。當你發現系統中存在「一個 vs. 多個」的條件判斷時,就應該考慮使用 COMPOSITE 來統一介面。

本章小結#

COMPOSITE 模式透過讓單一物件與組合物件實作相同介面,消除了客戶端對「單數/複數」的區分需求。這不僅簡化了程式碼,更讓系統更容易擴展——新增新的 Leaf 或 Composite 類型都不需要修改客戶端。