
當你發現自己寫了第三個 if (type === 'xxx') return new XxxPayment() 的時候,就是該用 Factory 的時候了。
先講結論
Factory Pattern 的核心就是:把「決定 new 哪個 class」這件事抽出去。呼叫端只要說「我要信用卡」,工廠就吐出信用卡物件,你不需要知道它怎麼被建出來的。好處?新增支付方式的時候,你不用改呼叫端的程式碼。
你一定遇過這種 code
// 這段 code 每次加新支付方式都要改,而且會越來越長
function createPayment(type, options) {
if (type === 'credit') return new CreditCardPayment(options);
if (type === 'paypal') return new PayPalPayment(options);
if (type === 'bitcoin') return new BitcoinPayment(options);
// 再加下去就要崩潰了...
}上面這段程式碼有什麼問題?每加一種支付方式,你就要回來改這個 function。違反開放封閉原則不說,code review 的人也會開始翻白眼。
用 Factory 重構
classDiagram class Payment { <<abstract>> +process(amount)* String } class CreditCardPayment { -cardNumber : String +process(amount) String } class PayPalPayment { -email : String +process(amount) String } class PaymentFactory { -paymentMethods : Map +createPayment(method, options) Payment } Payment <|-- CreditCardPayment Payment <|-- PayPalPayment PaymentFactory --> Payment
class Payment {
process(amount) {
throw new Error('process() 必須由子類別實作');
}
}
class CreditCardPayment extends Payment {
constructor({ cardNumber, cardHolder }) {
super();
this.cardNumber = cardNumber;
this.cardHolder = cardHolder;
}
process(amount) {
return `處理 ${this.cardHolder} 的信用卡支付 $${amount}`;
}
}
class PayPalPayment extends Payment {
constructor({ email }) {
super();
this.email = email;
}
process(amount) {
return `處理 ${this.email} 的 PayPal 支付 $${amount}`;
}
}
// 重點在這:工廠用 Map 管理,不用 if-else
class PaymentFactory {
constructor() {
this.paymentMethods = {
CreditCard: CreditCardPayment,
PayPal: PayPalPayment
};
}
createPayment(method, options) {
const PaymentMethod = this.paymentMethods[method];
if (!PaymentMethod) throw new Error('未知的支付方式');
return new PaymentMethod(options);
}
// 動態註冊——新增支付方式不用改工廠程式碼
addPaymentMethod(name, PaymentClass) {
this.paymentMethods[name] = PaymentClass;
}
}看到 addPaymentMethod 了嗎?這才是 Factory 最爽的地方——你可以在 runtime 動態註冊新的支付方式,完全不用改工廠本身的程式碼。
Factory 的三種口味
- Simple Factory:一個 method 搞定,適合種類少且穩定的情況
- Factory Method:把建立邏輯推給子類別,每個子類別決定自己要生什麼
- Abstract Factory:一次建立一整組相關物件(詳見 Abstract Factory 模式)
大多數情況下,Simple Factory 就夠用了。別為了用 pattern 而用 pattern。
什麼時候不該用 Factory?
如果你的系統只有一兩種物件,而且未來也不太會新增——直接 new 就好。Factory 是為了管理「種類會成長」的場景設計的。硬要包一層工廠,只會讓同事覺得你在炫技。
Factory Pattern 就像是程式界的代工廠:你下單、它出貨、你不用管生產線長什麼樣子。但如果你只需要一支螺絲起子,就不用蓋一座工廠了。
延伸閱讀
- Singleton 模式 — 工廠類別常搭配 Singleton
- Abstract Factory 模式 — 工廠模式的進階版本
- Strategy 模式 — 可與工廠搭配動態選擇演算法
- Builder 模式 — 另一種創建型模式