Alex Liang

[Design Pattern] 簡單工廠方法模式(Simple Factory)介紹與應用

最近重溫大話設計模式,對各個design pattern有更深的了解,試著介紹常用的幾種模式並說明適合的場景。

第一篇要介紹的是簡單工廠方法模式。

適合場景

有二個以上、功能相近但細節稍有不同的資料結構或實作,適合用簡單工廠方法模式。如薪資計算(正職、工讀生)、電商平台的寄件方式(宅急便、超商或郵局)。

以電商平台的寄件舉例,其共通的屬性有:

  1. 收件地址 (一般地址/超商門市)
  2. 運費
  3. 免運門檻
  4. 物流追蹤碼

若平台增加新的寄件方式,專案中有關寄件的程式碼都要新增條件才能避免錯誤。

範例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 class ConvenienceStoreDelivery {
constructor(shipAddress) {
this.shipAddress = shipAddress;
this.shippingRate = 100;
this.freeShipmentThreshold = 2000;
this.traceNumber = '';
}

get shippingRate() {
return this.shippingRate;
}

get freeShipmentThreshold() {
return this.freeShipmentThreshold;
}

set traceNumber() {}

get traceNumber() {
return this.traceNumber;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function  DeliveryFactory(provider, address) {
let deliveryProvider = null;
switch (provider) {
case 'convenience store':
deliveryProvider = new ConvenienceStoreDelivery(address);
break;
case 'post office'
deliveryProvider = new PostOfficeDelivery(address);
break;
default:
throw new Error(`Cannot recongize delivery provider ${provider}`);
}
return deliveryProvider
}

用戶端

1
2
const deliveryProvider = DeliveryFactory(provider, address);
// 其餘操作

注意事項

  • 假如實作端會隨著業務、流程不斷增加數量,則此方法每新增實作類別就必須增加case的分支。這會破壞開放-封閉原則。此時可考慮改用工廠方法
  • 此方法只針對物件建立問題,若實作類別的函式經常更動(如免運、折價),可考慮使用策略模式封裝實作。