C++设计模式:工厂方法模式

工厂方法模式是一种创建型设计模式,其核心是将对象的创建延迟到子类中,通过定义一个接口来创建对象,使得子类决定实例化哪一个类。它在需要扩展产品类型时特别有用,能够避免代码的重复和耦合。


工厂方法模式的核心概念

  1. 抽象产品(Product)
    定义产品的接口,描述产品的公共行为。
  2. 具体产品(ConcreteProduct)
    实现抽象产品接口,定义具体的产品功能。
  3. 抽象工厂(Creator/Factory)
    定义一个工厂方法接口,用于创建产品对象。
  4. 具体工厂(ConcreteCreator/ConcreteFactory)
    实现工厂方法,创建特定类型的产品对象。
  5. 客户端(Client)
    通过工厂方法获取具体产品实例,而无需关心具体产品的实现细节。

案例背景:文档生成器

假设一个文档处理系统需要根据用户需求生成不同类型的文档(如 Word 文档和 PDF 文档)。我们希望通过工厂方法模式实现以下目标:

  1. 灵活扩展:添加新文档类型时,无需修改现有代码。
  2. 解耦逻辑:客户端代码不直接依赖具体文档类,而是通过工厂方法动态创建。

代码实现:文档生成器
cpp 复制代码
#include <iostream>
#include <memory>
#include <string>

// 抽象产品类:定义文档接口
class Document {
public:
    virtual void open() const = 0;  // 打开文档的接口方法
    virtual ~Document() = default;
};

// 具体产品类:Word文档
class WordDocument : public Document {
public:
    void open() const override {
        std::cout << "打开Word文档。\n";
    }
};

// 具体产品类:PDF文档
class PDFDocument : public Document {
public:
    void open() const override {
        std::cout << "打开PDF文档。\n";
    }
};

// 抽象工厂类:定义文档工厂接口
class DocumentFactory {
public:
    virtual std::unique_ptr<Document> createDocument() const = 0;  // 工厂方法
    virtual ~DocumentFactory() = default;
};

// 具体工厂类:Word文档工厂
class WordDocumentFactory : public DocumentFactory {
public:
    std::unique_ptr<Document> createDocument() const override {
        return std::make_unique<WordDocument>();  // 创建具体的Word文档对象
    }
};

// 具体工厂类:PDF文档工厂
class PDFDocumentFactory : public DocumentFactory {
public:
    std::unique_ptr<Document> createDocument() const override {
        return std::make_unique<PDFDocument>();  // 创建具体的PDF文档对象
    }
};

// 客户端代码:通过工厂方法创建文档
void clientCode(const DocumentFactory& factory) {
    // 工厂方法生成文档实例
    auto document = factory.createDocument();
    document->open();  // 使用文档对象
}

int main() {
    std::cout << "客户端使用Word文档工厂:\n";
    WordDocumentFactory wordFactory;
    clientCode(wordFactory);

    std::cout << "\n客户端使用PDF文档工厂:\n";
    PDFDocumentFactory pdfFactory;
    clientCode(pdfFactory);

    return 0;
}

代码解析
  1. 抽象产品(Document)

    提供一个通用接口 open,定义所有文档的公共行为。

    cpp 复制代码
    class Document {
    public:
        virtual void open() const = 0;
        virtual ~Document() = default;
    };
  2. 具体产品(WordDocument 和 PDFDocument)

    分别实现 Document 接口,定义具体文档的行为。

    cpp 复制代码
    class WordDocument : public Document {
    public:
        void open() const override {
            std::cout << "打开Word文档。\n";
        }
    };
  3. 抽象工厂(DocumentFactory)

    定义一个接口 createDocument,负责创建文档对象。

    cpp 复制代码
    class DocumentFactory {
    public:
        virtual std::unique_ptr<Document> createDocument() const = 0;
        virtual ~DocumentFactory() = default;
    };
  4. 具体工厂(WordDocumentFactory 和 PDFDocumentFactory)

    分别实现抽象工厂接口,负责创建对应的文档对象。

    cpp 复制代码
    class WordDocumentFactory : public DocumentFactory {
    public:
        std::unique_ptr<Document> createDocument() const override {
            return std::make_unique<WordDocument>();
        }
    };
  5. 客户端代码

    客户端通过工厂方法获取具体的文档对象,完全解耦了具体产品的实现。

    cpp 复制代码
    void clientCode(const DocumentFactory& factory) {
        auto document = factory.createDocument();
        document->open();
    }

运行结果

复制代码
客户端使用Word文档工厂:
打开Word文档。

客户端使用PDF文档工厂:
打开PDF文档。

优缺点分析

优点
  1. 解耦对象创建与使用:客户端无需关心对象如何创建,专注于使用。
  2. 扩展性强:新增产品类型时,只需添加新的具体工厂类和产品类,无需修改现有代码。
  3. 符合单一职责原则:将对象的创建逻辑独立到工厂类中,便于维护。
缺点
  1. 类数量增加:每新增一个产品类型,就需要增加一个具体工厂类,可能导致类数量膨胀。
  2. 复杂度增加:相比直接实例化对象,工厂方法模式引入了更多的抽象和类层次。

适用场景

  1. 系统需要灵活创建对象:如根据不同条件动态创建不同类型的对象。
  2. 对象创建逻辑复杂:如需要对创建过程进行封装,避免在客户端暴露创建细节。
  3. 需要扩展性:系统需要频繁增加新对象类型。

改进方向

结合C++现代特性(如 std::unique_ptrstd::make_unique),可以使代码更加安全、简洁,并减少内存管理的复杂性。同时,可以将工厂与配置文件、命令行参数等结合,进一步提升灵活性。


总结

工厂方法模式是一个经典的创建型设计模式,它通过定义工厂接口和具体工厂,将对象的创建逻辑与使用逻辑分离,使得系统具有更好的扩展性和灵活性。在C++中,通过利用抽象类、继承和智能指针,可以高效实现工厂方法模式,并确保资源管理的安全性和代码的可维护性。

相关推荐
wqfhenanxc42 分钟前
Mixing C++ and Rust for Fun and Profit 阅读笔记
c++·笔记·rust
R-G-B1 小时前
【MFC】 VS2022打开低版本的MFC,双击.rc文件,DIalog加载失败,页面弹窗fatal error RC***:cannot open*****
c++·mfc·vs打开较早版本mfc·双击.rc文件·dialog加载失败·fatal error rc·cannot open
敲上瘾1 小时前
基于Tcp协议的应用层协议定制
linux·运维·服务器·网络·c++·网络协议·tcp/ip
桃酥4032 小时前
工厂模式:工厂方法模式 和 抽象工厂模式
工厂方法模式·抽象工厂模式
莹莹学编程—成长记2 小时前
string的模拟实现
服务器·c++·算法
lybugproducer2 小时前
创建型设计模式之:简单工厂模式、工厂方法模式、抽象工厂模式、建造者模式和原型模式
java·设计模式·建造者模式·简单工厂模式·工厂方法模式·抽象工厂模式·面向对象
喵先生!5 小时前
C++中的vector和list的区别与适用场景
开发语言·c++
xMathematics6 小时前
计算机图形学实践:结合Qt和OpenGL实现绘制彩色三角形
开发语言·c++·qt·计算机图形学·cmake·opengl
yuanManGan8 小时前
C++入门小馆: 深入了解STLlist
开发语言·c++
梁下轻语的秋缘8 小时前
每日c/c++题 备战蓝桥杯(P1049 [NOIP 2001 普及组] 装箱问题)
c语言·c++·学习·蓝桥杯