工厂方法模式通过抽象创建过程、利用继承实现解耦,使客户端无需依赖具体产品类,新增产品时只需添加对应工厂子类,符合开闭原则,并结合智能指针与虚析构函数可有效管理资源。

C++中实现工厂模式,特别是工厂方法模式,核心在于将对象的创建过程抽象化,并交由子类决定实例化哪个具体产品。它提供了一个接口来创建对象,但具体的类实例化则由其子类完成,这样一来,客户端代码就无需关心具体产品的创建细节,从而实现了创建者和具体产品之间的解耦。在我看来,这是一种非常优雅地处理对象创建复杂性的方式,尤其当你的系统需要支持多种同类型但具体实现不同的产品时。
要实现C++中的工厂方法模式,我们通常会定义一个抽象产品基类,一些具体的子产品类,一个抽象创建者基类,以及一些具体的创建者子类。
我们以一个简单的“文档”系统为例,假设我们有不同类型的文档(比如文本文档和图片文档),并且需要不同的工厂来创建它们。
#include <iostream>
#include <memory> // 为了使用智能指针
// 1. 抽象产品 (Abstract Product)
// 定义所有产品都应该遵循的接口
class Document {
public:
virtual ~Document() = default; // 确保多态删除
virtual void open() = 0;
virtual void save() = 0;
};
// 2. 具体产品 (Concrete Products)
// 实现抽象产品接口的具体类
class TextDocument : public Document {
public:
void open() override {
std::cout << "Opening a Text Document." << std::endl;
}
void save() override {
std::cout << "Saving a Text Document." << std::endl;
}
};
class ImageDocument : public Document {
public:
void open() override {
std::cout << "Opening an Image Document." << std::endl;
}
void save() override {
std::cout << "Saving an Image Document." << std::endl;
}
};
// 3. 抽象创建者 (Abstract Creator)
// 声明工厂方法,并可能包含一些操作,这些操作会使用工厂方法创建的产品
class DocumentCreator {
public:
virtual ~DocumentCreator() = default;
// 工厂方法:返回一个抽象产品指针
// 注意这里使用了std::unique_ptr来管理内存,避免裸指针的内存泄漏问题
virtual std::unique_ptr<Document> createDocument() = 0;
// 可以在这里定义一些通用的操作,这些操作会用到由工厂方法创建的产品
void operateDocument() {
std::unique_ptr<Document> doc = createDocument(); // 通过工厂方法创建产品
if (doc) {
doc->open();
doc->save();
std::cout << "Document operation completed." << std::endl;
} else {
std::cout << "Failed to create document." << std::endl;
}
}
};
// 4. 具体创建者 (Concrete Creators)
// 实现工厂方法,返回一个具体的具体产品实例
class TextDocumentCreator : public DocumentCreator {
public:
std::unique_ptr<Document> createDocument() override {
std::cout << "TextDocumentCreator is creating a TextDocument." << std::endl;
return std::make_unique<TextDocument>();
}
};
class ImageDocumentCreator : public DocumentCreator {
public:
std::unique_ptr<Document> createDocument() override {
std::cout << "ImageDocumentCreator is creating an ImageDocument." << std::endl;
return std::make_unique<ImageDocument>();
}
};
// 客户端代码
int main() {
std::cout << "--- Using Text Document Creator ---" << std::endl;
std::unique_ptr<DocumentCreator> textCreator = std::make_unique<TextDocumentCreator>();
textCreator->operateDocument(); // 客户端只与抽象创建者交互
std::cout << "\n--- Using Image Document Creator ---" << std::endl;
std::unique_ptr<DocumentCreator> imageCreator = std::make_unique<ImageDocumentCreator>();
imageCreator->operateDocument(); // 客户端只与抽象创建者交互
return 0;
}这段代码展示了工厂方法模式的核心结构。客户端代码(
main
DocumentCreator
TextDocument
ImageDocument
DocumentCreator
立即学习“C++免费学习笔记(深入)”;
在我看来,工厂方法模式在C++项目中特别有价值,它主要解决了几个我在实际开发中经常遇到的痛点:
首先,它彻底解耦了客户端代码与具体产品类之间的依赖。想象一下,如果你的应用程序需要根据不同的配置或用户输入来创建不同类型的对象,但你又不想在客户端代码里写一大堆
if-else
switch
new
其次,它很好地遵循了“开闭原则”(Open/Closed Principle)。这意味着你的系统对扩展是开放的,对修改是封闭的。当需要引入一个新的产品类型(比如“PDF文档”)时,你只需要创建新的
PdfDocument
PdfDocumentCreator
再者,它将对象创建的复杂逻辑集中管理。有时候,一个对象的创建过程可能不仅仅是
new
这三个概念初学者确实容易混淆,我当初也花了点时间才理清。在我看来,它们虽然都和“创建对象”有关,但解决问题的层次和方式却大相径庭。
简单工厂模式(Simple Factory Pattern),严格来说,它不算一个设计模式,更多是一种编程习惯或者说技巧。它的特点是有一个集中的工厂类,通常包含一个静态方法,根据传入的参数来决定创建哪种具体产品。比如,
DocumentFactory::createDocument(type)
工厂方法模式(Factory Method Pattern),就是我们上面讨论的。它的核心在于“多态性”和“继承”。它定义了一个抽象的工厂接口,由子类去实现具体的工厂方法,从而生产出对应的产品。每个具体产品都有一个对应的具体工厂来创建。你看,
TextDocumentCreator
TextDocument
ImageDocumentCreator
ImageDocument
PdfDocument
PdfDocument
PdfDocumentCreator
抽象工厂模式(Abstract Factory Pattern),这个模式就更高级一些了,它解决的是创建“产品族”的问题。简单来说,如果你不仅仅需要创建一种产品(比如文档),还需要创建一系列相关的产品(比如文档编辑器、文档查看器、文档打印机),并且这些产品需要保持一致的“风格”(比如都是“Windows风格”的,或者是“Mac风格”的),那么抽象工厂就派上用场了。它提供一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们具体的类。抽象工厂模式通常会包含多个工厂方法,每个方法负责创建产品族中的一个产品。很多时候,抽象工厂的实现内部,会用到工厂方法模式来创建具体的产品。它就像一个超级工厂,能一次性生产一套完整的、风格一致的产品线。
简单总结一下:
在C++里实现工厂方法模式,虽然概念上很清晰,但有些细节如果不注意,确实容易踩坑,或者写出不够健壮的代码。
一个最常见的,也是最致命的陷阱就是内存管理问题。因为工厂方法通常返回一个指向新创建对象的指针(
Product*
delete
std::unique_ptr
std::shared_ptr
std::unique_ptr
unique_ptr
另一个需要注意的点是虚析构函数(Virtual Destructors)。当你的工厂方法返回一个基类指针(
Document*
TextDocument
delete
Document
DocumentCreator
此外,类的数量可能会增加。工厂方法模式的“代价”就是引入了更多的类。每增加一种产品,你可能需要增加一个产品类和一个对应的工厂类。对于非常简单的场景,这种模式可能会显得有些“杀鸡用牛刀”,增加了不必要的复杂性。所以,在决定使用工厂模式前,最好评估一下项目的规模和未来扩展的可能性。如果产品种类很少且稳定,简单工厂或者直接
new
最后,工厂方法的参数设计。有时候,产品的创建可能需要一些参数。工厂方法可以接受这些参数,比如
createDocument(std::string name)
总而言之,工厂方法模式是一个非常实用的设计模式,但C++的特性(尤其是内存管理)要求我们在使用时更加细致和严谨。用好智能指针和虚析构函数,能让你的工厂模式代码既灵活又健壮。
以上就是c++++如何实现工厂模式_c++设计模式之工厂方法模式解析的详细内容,更多请关注php中文网其它相关文章!
c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号