工廠方法 是一種建立型設計模式,定義一個建立物件的介面,但由子類別決定實例化哪個具體類別。核心意圖:**將物件建立的責任委派給子類別,實現「開放封閉原則」**。
+----------------+ +------------------+
| Product |◄─────────| ConcreteProduct |
| (介面/抽象類別) | 實作 | (具體產品) |
+----------------+ +------------------+
▲
| 建立
+----------------+ +-------------------+
| Creator |◄─────────| ConcreteCreator |
| (抽象建立者) | 工廠方法 | (具體建立者) |
| +CreateProduct()| 重寫 | +CreateProduct() |
| +GetProduct() | +-------------------+
+----------------+
| 角色 | 職責 |
|---|---|
| Product | 定義產品介面 |
| ConcreteProduct | 實作產品介面 |
| Creator | 宣告工廠方法 `CreateProduct()`,可提供預設實作;提供 `GetProduct()` 管理實例生命週期 |
| ConcreteCreator | 重寫 `CreateProduct()` 回傳具體產品實例 |
#ifndef FACTORY_H
#define FACTORY_H
class Product {
public:
virtual ~Product() = default;
};
class Creator {
public:
Creator() : m_pProduct(nullptr) {}
virtual ~Creator() { delete m_pProduct; }
Product* GetProduct() {
if (!m_pProduct)
m_pProduct = CreateProduct(); // 延遲建立
return m_pProduct;
}
virtual Product* CreateProduct() = 0; // 純虛擬工廠方法
private:
Product* m_pProduct;
};
// 模板化標準建立者:消除為每個產品寫 ConcreteCreator 的需求
template
class StandardCreator : public Creator {
public:
Product* CreateProduct() override {
return new TheProduct();
}
};
#endif
#include "factory.h"
#include
using namespace std;
// 客戶端只需定義具體產品類別
class MyProduct : public Product {
public:
MyProduct() { cout << "MyProduct has been constructed!" << endl; }
};
class YourProduct : public Product {
public:
YourProduct() { cout << "YourProduct has been constructed!" << endl; }
};
class OurProduct : public Product {
public:
OurProduct() { cout << "OurProduct has been constructed!" << endl; }
};
int main() {
// 使用模板化建立者,無需寫 ConcreteCreator 子類別
StandardCreator ourCreator;
Product* p = ourCreator.GetProduct();
StandardCreator myCreator;
p = myCreator.GetProduct();
StandardCreator yourCreator;
p = yourCreator.GetProduct();
cin.get();
return 0;
}
MyProduct has been constructed! YourProduct has been constructed! OurProduct has been constructed!
`GetProduct()` 中首次呼叫時才建立實例 (Lazy Initialization),避免不必要的資源佔用。
解決「為了建立不同產品必須建立對應 ConcreteCreator 子類別」的類別爆炸問題。C++ 模板在編譯期具現化,效能零開銷。
`Creator` 析構函數負責刪除產品,實作簡單擁有權語意。現代 C++ 建議改用 `std::unique_ptr
| 模式 | 核心差異 | 適用場景 |
|---|---|---|
| 簡單工廠 | 單一工廠類別含 `switch`/`if` 判斷建立什麼產品 | 產品類別固定、較少、客戶端不關心建立細節 |
| 工廠方法 | **每個產品對應一個建立者子類別** (或模板具現化),建立邏輯分散 | 產品擴展頻繁、希望符合開放封閉原則、框架預留擴展點 |
| 抽象工廠 | 建立**相關/依賴的產品家族**,介面含多個工廠方法 | 系統需支援多個產品族 (如跨平台 UI:WinButton/MacButton, WinMenu/MacMenu) |
工廠方法模式透過多型將「建立什麼」與「如何使用」解耦,是框架設計中提供擴展點的基石模式。C++ 模板機制讓其實現更加優雅高效。