提供一個介面,用來建立「一整族互相搭配的產品」,呼叫端只拿抽象產品、不知道也不在乎背後是哪一套具體實作,換整套只要換一個工廠物件。
🧠 When to Use
TIP
訊號:你的產品是「成套」出現的——Windows 的 Button + Checkbox + Menu,或 Mac 的那一套——而且絕對不能混搭。換主題、換平台、換資料庫方言時想一次切換整族。
- 系統要獨立於產品的建立與組合,且產品有多個系列(family)。
- 同一族產品必須一起使用、不可跨族混用(風格一致性約束)。
- 想在執行期或設定檔層級整套替換實作,而不改用到產品的程式。
⚖️ Structure & Variants
經典版 — 一個工廠介面產出一族產品
interface Button; interface Checkbox
interface GUIFactory { // 抽象工廠:定義一族產品的建立
fun createButton(): Button
fun createCheckbox(): Checkbox
}
class WinFactory : GUIFactory {
override fun createButton() = WinButton()
override fun createCheckbox() = WinCheckbox()
}
class MacFactory : GUIFactory {
override fun createButton() = MacButton()
override fun createCheckbox() = MacCheckbox()
}
// 用組合:把工廠傳進來,整套實作由它決定
class App(factory: GUIFactory) {
private val button = factory.createButton()
private val checkbox = factory.createCheckbox()
}- 換平台只換
factory這一個物件,App完全不動,且保證同族不混搭。
與 Factory Method 的差別
- Factory Method:單一產品的建立,靠繼承(子類 override 一個方法)。
- Abstract Factory:一族相關產品的建立,靠組合(傳入一個 factory 物件)。
- 抽象工廠內部的每個方法,往往本身就是一個工廠方法。
退化形 — 只剩一個方法時
- 當一族只剩一個產品,抽象工廠就退化回工廠方法;硬留多介面只是過度設計。
- 反之產品族很大、建立過程又複雜,常和 Builder 搭配:工廠決定「哪一族」,builder 負責「怎麼組」。
⚠️ Misuse & Anti-patterns
- 產品族不會增加卻硬上:抽象工廠擅長加「新的一族」,但加新產品種類要改所有工廠介面與實作——若產品種類常變,這模式會很痛。
- 只有一個系列:根本沒有第二族時,整套抽象層只是間接層,直接
new或工廠方法更清楚。 - 偷偷跨族混用:拿
WinFactory的 Button 配MacFactory的 Checkbox,等於繞過了模式存在的唯一理由(風格一致性)。
🔑 Takeaways
- 解決的是「一整族產品的一致建立與整套替換」,呼叫端只依賴抽象產品。
- 用組合(傳入工廠)而非繼承;換實作就換工廠,保證同族不混搭。
- 擅長加「新系列」、不擅長加「新產品種類」——產品種類常變就別用。
No notes yet — jot your takeaways or Q&A here.