組合 (Composite)

★★★★★Studied

FromDesign Patterns (GoF)大話設計模式

📚 From the Books

組合 (Composite)ConceptStructural

把物件組成樹狀結構,讓 client 用同一套介面對待「單一葉子」與「物件群組」,遞迴處理整棵樹時不必區分兩者。

🧠 When to Use

TIP

訊號:你的資料是部分-整體的層級結構(檔案/資料夾、UI 元件、選單),而 client 不想為「單個」和「一群」寫兩套邏輯。

⚖️ Structure & Variants

經典版 — 葉子與組合同介面
interface FileNode { fun size(): Int }

// 葉子
class File(private val bytes: Int) : FileNode {
    override fun size() = bytes
}

// 組合節點:持有子節點,遞迴彙總
class Folder(private val children: List<FileNode>) : FileNode {
    override fun size() = children.sumOf { it.size() }
}

val tree = Folder(listOf(File(100), Folder(listOf(File(20), File(30)))))
tree.size()   // 150,client 不必區分 File / Folder
  • 關鍵:Folder 也是 FileNode,所以可以無限巢狀、統一呼叫。
安全性 vs 透明性的取捨
  • 透明版:把 add/remove 放在共同介面——client 全透明,但葉子得提供無意義的 add(或丟例外)。
  • 安全版add/remove 只放在 Composite——型別安全,但 client 得做型別判斷。
  • GoF 偏透明(重一致性);實務看是否常需動態增刪子節點。
常搭配的模式
  • Iterator:統一走訪整棵樹的節點。
  • Visitor:對不同節點型別套用不同操作,又不汙染節點類別。

⚠️ Misuse & Anti-patterns

🔑 Takeaways

✍️ My Notes

No notes yet — jot your takeaways or Q&A here.

📖 Further Reading