C++实现设计模式---工厂方法模式 (Factory Method)

ops/2025/1/17 0:21:26/

工厂方法模式 (Factory Method)

工厂方法模式是一种创建型设计模式,提供一个创建对象的接口,让子类决定实例化哪个类,从而实现了对对象创建过程的解耦和扩展。


意图

  • 定义一个用于创建对象的接口,允许子类决定具体实例化哪个类。
  • 把对象创建的职责交给子类,使得系统更灵活,符合 开闭原则

使用场景

  1. 运行时决定类的实例化
    • 如果对象的具体类型在编译时无法确定,而需要在运行时根据条件选择。
  2. 隐藏对象的复杂创建过程
    • 如果创建对象的过程复杂且容易重复,可以使用工厂方法集中管理。
  3. 需要对对象的创建进行扩展
    • 当需要新增产品类时,可以通过增加新的具体工厂类,而不修改已有代码。

参与者角色

  1. 工厂基类 (Creator)

    • 定义创建产品对象的接口,通常包含一个抽象的 createProduct() 方法。
    • 有时可以包含产品创建的默认实现。
  2. 具体工厂类 (Concrete Creator)

    • 实现 createProduct() 方法,负责实例化具体的产品。
  3. 产品基类 (Product)

    • 定义所有产品的公共接口。
  4. 具体产品类 (Concrete Product)

    • 实现产品基类的接口,提供产品的具体功能。

示例代码

以下示例通过工厂方法模式实现了动态创建产品的功能。

#include <iostream>
#include <memory>// 产品基类
class Product {
public:virtual void use() const = 0;virtual ~Product() {}
};// 具体产品 A
class ConcreteProductA : public Product {
public:void use() const override {std::cout << "Using Product A" << std::endl;}
};// 具体产品 B
class ConcreteProductB : public Product {
public:void use() const override {std::cout << "Using Product B" << std::endl;}
};// 工厂基类
class Factory {
public:virtual std::unique_ptr<Product> createProduct() const = 0;virtual ~Factory() {}
};// 具体工厂 A
class FactoryA : public Factory {
public:std::unique_ptr<Product> createProduct() const override {return std::make_unique<ConcreteProductA>();}
};// 具体工厂 B
class FactoryB : public Factory {
public:std::unique_ptr<Product> createProduct() const override {return std::make_unique<ConcreteProductB>();}
};// 主函数
int main() {FactoryA factoryA;FactoryB factoryB;auto productA = factoryA.createProduct();auto productB = factoryB.createProduct();productA->use(); // 输出:Using Product AproductB->use(); // 输出:Using Product Breturn 0;
}

代码解析

1. 产品基类

定义了所有产品的公共接口,确保具体产品具有一致的功能。例如:

class Product {
public:virtual void use() const = 0;virtual ~Product() {}
};

2. 具体产品类

具体产品类实现了产品基类接口,并提供具体的功能实现:

class ConcreteProductA : public Product {
public:void use() const override {std::cout << "Using Product A" << std::endl;}
};

3. 工厂基类

工厂基类声明了创建产品的接口,具体工厂将实现该接口:

class Factory {
public:virtual std::unique_ptr<Product> createProduct() const = 0;virtual ~Factory() {}
};

4. 具体工厂类

每个具体工厂类实现了 createProduct() 方法,并实例化具体的产品:

class FactoryA : public Factory {
public:std::unique_ptr<Product> createProduct() const override {return std::make_unique<ConcreteProductA>();}
};

5. 主函数

客户端代码通过工厂接口创建产品,而无需知道具体产品的实现细节:

FactoryA factoryA;
auto productA = factoryA.createProduct();
productA->use(); // 输出:Using Product A

优缺点

优点

  1. 符合开闭原则
    • 新增产品只需新增具体工厂类,无需修改已有代码。
  2. 解耦
    • 客户端代码只依赖于工厂接口和产品接口,具体产品的实现细节被隐藏。
  3. 灵活性
    • 可以动态选择和创建具体产品。

缺点

  1. 增加复杂性
    • 每个产品都需要对应的具体工厂类,可能导致类的数量增加。
  2. 需要额外的抽象
    • 增加了工厂基类和产品基类的抽象层。

适用场景

  • 动态选择产品:如根据配置文件决定创建哪个产品。
  • 封装复杂创建过程:如隐藏产品创建的复杂逻辑。
  • 需要扩展性:如未来可能新增产品类型。

改进与扩展

  1. 结合配置文件
    动态读取配置,根据配置内容选择具体工厂:

    std::unique_ptr<Factory> factory;
    if (config == "A") {factory = std::make_unique<FactoryA>();
    } else {factory = std::make_unique<FactoryB>();
    }
    auto product = factory->createProduct();
    product->use();
    
  2. 结合抽象工厂模式
    如果需要创建一组相关的产品,可以将工厂方法扩展为抽象工厂模式。


总结

工厂方法模式通过定义创建对象的接口,将对象的创建与使用分离,提高了代码的扩展性和灵活性。
它适合需要动态选择产品类型或需要隐藏对象创建细节的场景。


http://www.ppmy.cn/ops/150672.html

相关文章

编译pytorch——cuda-toolkit-nvcc

链接 https://blog.csdn.net/wjinjie/article/details/108997692https://docs.nvidia.com/cuda/cuda-installation-guide-linux/#switching-between-driver-module-flavorshttps://forums.developer.nvidia.com/t/can-not-load-nvidia-drivers-on-ubuntu-22-10/239750https://…

Docker常用命令大全

Docker容器相关命令&#xff1a; 创建并启动容器&#xff1a; docker run&#xff1a;创建一个新的容器并运行一个命令。例如&#xff1a;docker run -d -p 8080:80 nginx这将后台(-d)运行一个Nginx容器&#xff0c;并映射宿主机的8080端口到容器的80端口。 列出容器&#x…

ajax与json

目录 1、ajax1.1、什么是ajax1.2、ajax核心AJAX 工作原理示例代码重要属性和方法兼容性 1.3、jQuery ajax什么是jQuery ajaxjQuery AJAX 核心概念基本用法1. **使用 $.ajax() 方法**2. **使用简化方法****使用 $.get() 方法****使用 $.post() 方法** 常用配置选项示例&#xff…

Termora 一个开源的 SSH 跨平台客户端工具

Termora 是一个终端模拟器和 SSH 客户端&#xff0c;支持 Windows&#xff0c;macOS 和 Linux。 功能特性 支持 SSH 和本地终端支持 SFTP 文件传输支持 Windows、macOS、Linux 平台支持 Zmodem 协议支持 SSH 端口转发支持配置同步到 Gist支持宏&#xff08;录制脚本并回放&…

c++ 手写queue循环队列

继承与多态 继承 父子出现同名的成员问题 #include <iostream>using namespace std; //父子类中出现重名成员 //定义一个父类 class Father{ public:string name; protected:int pwd; private:int money; public:Father(){cout<<"Father::构造"<&l…

从玩具到工业控制--51单片机的跨界传奇【2】

咱们在上一篇博客里面讲解了什么是单片机《单片机入门》&#xff0c;让大家对单片机有了初步的了解。我们今天继续讲解一些有关单片机的知识&#xff0c;顺便也讲解一下我们单片机用到的C语言知识。如果你对C语言还不太了解的话&#xff0c;可以看看博主的C语言专栏哟&#xff…

如何通过 Zero Trust 模型防止内外部威胁?

随着网络攻击方式的不断演化&#xff0c;传统的安全防护措施逐渐暴露出明显的不足。无论是企业内部员工的操作失误&#xff0c;还是外部黑客的精心策划&#xff0c;传统的“边界防御”模式已不再能够有效地应对日益复杂的网络威胁。为了应对这些挑战&#xff0c;Zero Trust&…

OpenGL中Shader LOD失效

1&#xff09;OpenGL中Shader LOD失效 2&#xff09;DoTween的GC优化 3&#xff09;开发微信小程序游戏有没有类似Debug真机图形的方法 4&#xff09;射线和Mesh三角面碰撞检测的算法 这是第418篇UWA技术知识分享的推送&#xff0c;精选了UWA社区的热门话题&#xff0c;涵盖了U…