工廠模式是一種創建型設計模式,用于封裝對象的創建過程。其核心在于定義一個工廠接口和多個具體工廠類,每個具體工廠負責實例化特定類型的產品;產品通過抽象類或接口定義,具體產品實現該接口。客戶端代碼通過工廠接口創建對象,無需了解具體實現細節。應用場景包括:1. 創建邏輯復雜時封裝初始化步驟;2. 需要靈活切換對象類型時根據條件選擇不同工廠;3. 隱藏創建細節以降低耦合度;4. 遵循開閉原則便于擴展新產品。工廠模式與抽象工廠的區別在于前者創建單一對象,后者創建一組相關對象。為避免內存泄漏,可使用智能指針、確保工廠釋放對象或采用raii機制管理資源。
工廠模式是一種創建型設計模式,它提供了一種創建對象的接口,但允許子類決定實例化哪個類。簡單來說,就是把對象的創建過程封裝起來,讓客戶端代碼只需要關心“我需要什么”,而不需要關心“怎么創建”。
解決方案
c++ 中實現工廠模式,核心在于定義一個工廠接口(抽象類),以及一個或多個具體的工廠類。每個具體工廠類負責創建特定類型的對象。
立即學習“C++免費學習筆記(深入)”;
-
定義產品接口(抽象類): 這是所有將被創建的對象的基類或接口。
class Product { public: virtual ~Product() {} virtual void use() = 0; // 純虛函數,強制子類實現 };
-
定義具體產品類: 這些類實現 Product 接口,是實際被創建的對象。
class ConcreteProductA : public Product { public: void use() override { std::cout << "Using ConcreteProductA" << std::endl; } }; class ConcreteProductB : public Product { public: void use() override { std::cout << "Using ConcreteProductB" << std::endl; } };
-
定義工廠接口(抽象類): 聲明一個創建 Product 對象的抽象方法。
class Factory { public: virtual ~Factory() {} virtual Product* createProduct() = 0; // 純虛函數 };
-
定義具體工廠類: 實現 Factory 接口,負責創建特定類型的 Product 對象。
class ConcreteFactoryA : public Factory { public: Product* createProduct() override { return new ConcreteProductA(); } }; class ConcreteFactoryB : public Factory { public: Product* createProduct() override { return new ConcreteProductB(); } };
-
客戶端代碼: 使用工廠來創建對象,而無需知道具體類的細節。
int main() { Factory* factoryA = new ConcreteFactoryA(); Product* productA = factoryA->createProduct(); productA->use(); // 輸出: Using ConcreteProductA Factory* factoryB = new ConcreteFactoryB(); Product* productB = factoryB->createProduct(); productB->use(); // 輸出: Using ConcreteProductB delete productA; delete factoryA; delete productB; delete factoryB; return 0; }
何時應該使用工廠模式?
工廠模式并非萬能藥。 它最適合以下場景:
- 創建對象的邏輯復雜: 如果對象的創建涉及復雜的依賴關系、配置或初始化步驟,工廠模式可以將這些復雜性封裝起來。
- 需要靈活地切換對象類型: 如果需要在運行時根據不同的條件創建不同的對象,工廠模式可以提供這種靈活性。例如,根據配置文件或者用戶輸入來選擇創建哪個具體的產品類。
- 隱藏對象的創建細節: 客戶端代碼只需要知道工廠接口,而不需要知道具體類的實現細節。這可以降低耦合度,提高代碼的可維護性。
- 遵循開閉原則: 當需要添加新的產品類型時,只需要添加新的具體產品類和具體工廠類,而不需要修改現有的代碼。
工廠模式與抽象工廠模式的區別是什么?
初學設計模式時,很容易將工廠模式和抽象工廠模式混淆。 簡單來說,工廠模式負責創建單個對象,而抽象工廠模式負責創建一組相關的對象。
想象一下,你要開一家電腦配件店。
- 工廠模式: 相當于你有一個專門生產 CPU 的工廠,另一個專門生產內存的工廠。每個工廠只負責生產一種類型的配件。
- 抽象工廠模式: 相當于你有一個專門生產 Intel 平臺的電腦配件工廠,另一個專門生產 AMD 平臺的電腦配件工廠。每個工廠負責生產一套完整的、相互兼容的配件。
抽象工廠模式通常包含多個工廠方法,每個工廠方法負責創建一種類型的對象。 這些對象通常屬于同一個產品族,并且彼此之間存在依賴關系。
如何避免工廠模式中的內存泄漏?
C++ 中手動管理內存是工廠模式中需要特別注意的地方。 上面的例子中,我們使用了 new 創建對象,這意味著我們需要手動 delete 釋放內存。
以下是一些避免內存泄漏的策略:
- 使用智能指針: std::unique_ptr 和 std::shared_ptr 可以自動管理對象的生命周期,避免忘記釋放內存。 例如,可以將 createProduct() 方法的返回值類型改為 std::unique_ptr
。 - 確保工廠負責釋放對象: 如果工廠負責創建對象,也應該負責釋放對象。 可以提供一個 destroyProduct() 方法,用于釋放由工廠創建的對象。
- 使用 RAII (Resource Acquisition Is Initialization): 將資源的獲取和釋放與對象的生命周期綁定在一起。 例如,可以創建一個專門用于管理 Product 對象生命周期的類。
修改后的示例,使用智能指針:
#include <memory> class Factory { public: virtual ~Factory() {} virtual std::unique_ptr<Product> createProduct() = 0; }; class ConcreteFactoryA : public Factory { public: std::unique_ptr<Product> createProduct() override { return std::make_unique<ConcreteProductA>(); } }; int main() { ConcreteFactoryA factory; std::unique_ptr<Product> product = factory.createProduct(); product->use(); // 使用 product // product 會在離開作用域時自動被銷毀,無需手動 delete return 0; }
使用智能指針能顯著簡化內存管理,降低出錯的可能性。