🎯 什麼情境該想到我

當你「面對的是樹狀、可以無限巢狀的結構(檔案與資料夾、UI 元件樹、選單與子選單、組織圖),而且希望客戶端不必分辨『這是單一葉子還是一整個容器』,用同一套呼叫就能處理」的時候。

⚙️ 怎麼用(步驟 / 公式)

意圖:把物件組合成樹狀結構以表示「部分—整體」的層級關係,讓客戶端能一致地對待單一物件(葉子)與物件的組合(容器)。

主要參與者 / 結構:

  • Component(元件):葉子與容器共同的介面,宣告共通操作(如 operation)。
  • Leaf(葉子):沒有子節點的終端物件,實作共通操作。
  • Composite(組合):持有一份子 Component 清單,實作共通操作時通常會遞迴轉發給子節點;並提供 add / remove / getChild 等管理子節點的方法。
  • Client:只透過 Component 介面操作整棵樹。

做法要點:

  1. 抽出葉子與容器都要有的操作,定義成 Component 介面。
  2. Leaf 直接實作;Composite 持有子節點清單,並在實作操作時遍歷子節點遞迴呼叫。
  3. 客戶端一律以 Component 型別操作,不需 if 判斷是葉子還是容器。

🧪 我實際套用的紀錄

  • (待填)

⚠️ 注意 / 什麼時候不適用

  • 核心取捨:把 add / remove 放在 Component 介面(透明性佳、客戶端統一)會讓「葉子也有 add/remove」在型別上說不通、需在葉子丟例外;只放在 Composite(型別安全)則客戶端得先判斷型別才能加子節點——透明性與型別安全難以兩全。
  • 容易讓設計變得過度一般化,什麼都塞進同一介面。
  • 若結構其實不是樹、或只有一兩層固定深度,直接用清單就好,不必動用此模式。

🔗 相關工具