cover

你的電商平台要做國際化:美國市場的稅制、幣別、物流跟台灣完全不同。你想確保「美國版」用的所有元件都是美國規格,不會不小心混到台灣的稅率計算。

這就是 Abstract Factory 的場景:確保一整組產品彼此相容

先講結論

Abstract Factory 提供一個介面來建立「一組相關的產品」。使用端只跟抽象工廠互動,不需要知道具體用的是哪一套產品。換一個工廠,就換一整套產品。

classDiagram
    class AbstractFactory {
        <<abstract>>
        +createProductA()* ProductA
        +createProductB()* ProductB
    }
    class USFactory {
        +createProductA() USProductA
        +createProductB() USProductB
    }
    class ProductA {
        <<abstract>>
        +use()* String
    }
    class USProductA {
        +use() String
    }
    AbstractFactory <|-- USFactory
    ProductA <|-- USProductA
    USFactory ..> USProductA : creates

跟普通 Factory 差在哪?

  • Factory:建立「一種產品」的不同變體(信用卡、PayPal、Bitcoin)
  • Abstract Factory:建立「一組產品」,確保它們彼此相容(美國的 Product A + 美國的 Product B)

簡單說:Factory 是挑口味,Abstract Factory 是挑套餐。

實戰:跨區域產品組合

Abstract Factory 模式:不同工廠產出一致風格的產品家族

// 抽象產品
class TaxCalculator {
    calculate(amount) { throw new Error('必須實作'); }
}
 
class ShippingService {
    getRate() { throw new Error('必須實作'); }
}
 
// 美國版
class USTaxCalculator extends TaxCalculator {
    calculate(amount) { return amount * 0.08; } // 8% 稅
}
 
class USShippingService extends ShippingService {
    getRate() { return 15; } // $15 運費
}
 
// 台灣版
class TWTaxCalculator extends TaxCalculator {
    calculate(amount) { return amount * 0.05; } // 5% 稅
}
 
class TWShippingService extends ShippingService {
    getRate() { return 60; } // NT$60 運費
}
 
// 工廠
class USFactory {
    createTaxCalculator() { return new USTaxCalculator(); }
    createShippingService() { return new USShippingService(); }
}
 
class TWFactory {
    createTaxCalculator() { return new TWTaxCalculator(); }
    createShippingService() { return new TWShippingService(); }
}
 
// 使用端完全不知道具體用哪一套
function checkout(factory, amount) {
    const tax = factory.createTaxCalculator();
    const shipping = factory.createShippingService();
 
    const taxAmount = tax.calculate(amount);
    const shippingRate = shipping.getRate();
 
    console.log(`稅: ${taxAmount}, 運費: ${shippingRate}`);
}
 
checkout(new USFactory(), 100);  // 稅: 8, 運費: 15
checkout(new TWFactory(), 100);  // 稅: 5, 運費: 60

checkout 函式不管你傳的是美國工廠還是台灣工廠——它只管呼叫 createTaxCalculator()createShippingService()。換一個工廠,就換一整套規格。

什麼時候不需要?

如果你的「產品」之間沒有相容性問題(用美國稅率搭台灣運費也不會出事),那用普通的 Factory 就好了。Abstract Factory 是為了「一組產品必須配套」的場景設計的。


Abstract Factory 就像去 IKEA 買整套家具——你選了北歐風系列,桌椅櫃子就都是同一個風格。不會出現把工業風鐵架跟古典木椅混搭的慘況


延伸閱讀