把「決定要 new 哪個具體類別」延後到子類別(或一個方法),讓呼叫端只依賴抽象介面,不被綁死在某個
new ConcreteX()。
🧠 When to Use
TIP
訊號:你發現程式裡散落著 new,而且每次要換實作就得改一堆地方;或一段流程是固定的,只有「建立哪個物件」這一步會變。
- 上層流程穩定,但用到的物件型別會依情境而變(依設定、依平台、依輸入)。
- 想讓「使用物件的程式」與「建立物件的程式」分離,方便測試時換成假物件。
- 框架想定義骨架、把「產生哪個元件」的決定權留給使用者子類別。
⚖️ Structure & Variants
經典版 — 抽象 creator + 子類別 override
abstract class Dialog {
fun render() { // 固定流程(Template Method 味道)
val button = createButton() // 工廠方法:交給子類別決定
button.onClick()
}
abstract fun createButton(): Button // ← 工廠方法
}
class WindowsDialog : Dialog() {
override fun createButton() = WindowsButton()
}- 流程在父類,「建立哪個 Button」由子類決定。新增一種 Button 只要加一個子類,不動
render()。
簡單工廠 (Simple Factory) — 嚴格說不是 GoF 模式
- 一個靜態方法用
when/switch依參數回傳具體型別。簡單直接,但每加一型就要改那個 switch(違反 OCP)。 - 適合型別少又穩定;型別會長就升級成工廠方法 / 抽象工廠。
與 Abstract Factory 的差別
- Factory Method:一個產品的建立,用繼承(override 一個方法)。
- Abstract Factory:一族相關產品的建立,用組合(傳入一個 factory 物件)。
- 兩者常一起出現:抽象工廠內部各個方法往往就是工廠方法。
⚠️ Misuse & Anti-patterns
- 為了用而用:型別只有一種、未來也不會變,硬包一層工廠只是徒增間接層。先 YAGNI。
- 簡單工廠 + 巨大 switch:把所有
new塞進一個不斷膨脹的when,每加一型都要改它——這正是要用策略 / 多型消滅的味道。 - 和 DI 容器打架:有了依賴注入容器後,很多「建立」的需求容器就能滿足,不必每處都自寫工廠。
🔑 Takeaways
- 本質是「把 new 的決定權往外推 / 往下推」,讓使用端只依賴抽象。
- 先問值不值得:型別會變、要可測、要可擴充才用;否則直接
new最清楚。 - Factory Method(繼承、單一產品)↔ Abstract Factory(組合、產品家族)要分清。
No notes yet — jot your takeaways or Q&A here.