建造者 (Builder)

★★★★Studied

FromDesign Patterns (GoF)大話設計模式Design Patterns Explained

📚 From the Books

建造者 (Builder)ConceptCreational

把「一步步組裝複雜物件」的過程從物件本身抽出來,讓同一套組裝步驟能產生不同表示,也讓呼叫端不必面對一長串難讀的建構子參數。

🧠 When to Use

TIP

訊號:你的建構子變成 Pizza(true, false, true, 12, null, "thin") 這種伸縮建構子 (telescoping constructor),參數一多就分不清誰是誰,而且很多是可選的。

⚖️ Structure & Variants

Fluent Builder — 鏈式呼叫逐步組裝
class Burger private constructor(
    val bun: String, val patties: Int, val cheese: Boolean,
) {
    class Builder(private val bun: String) {     // 必填走建構子
        private var patties = 1
        private var cheese = false
        fun patties(n: Int) = apply { patties = n }   // 回傳 this → 可鏈接
        fun cheese() = apply { cheese = true }
        fun build() = Burger(bun, patties, cheese)    // 最後才產出不可變物件
    }
}

val b = Burger.Builder("brioche").patties(2).cheese().build()
  • 必填參數放 Builder 建構子、可選參數用鏈式方法;build() 一次組出不可變成品。
Kotlin 慣用對照 — named args / apply
  • Kotlin 有具名參數 + 預設值,很多「可選欄位」場景根本不需要手寫 Builder:Burger(bun = "brioche", patties = 2)
  • 需要的是配置式 DSL 時才寫 builder,搭配 apply { } 或 trailing lambda 做出 html { body { ... } } 那種巢狀建構語法。
與 Abstract Factory / Prototype 的差別
  • Builder:重點在怎麼一步步組一個複雜物件,回傳的是「最終成品」。
  • Abstract Factory:重點在回傳「一族產品」,一次一個方法、不講組裝順序。
  • Prototype:不組裝,直接複製既有物件當起點。

⚠️ Misuse & Anti-patterns

🔑 Takeaways

✍️ My Notes

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

📖 Further Reading