Bootstrap

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

工厂方法模式 (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 A
    productB->use(); // 输出:Using Product B

    return 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. 结合抽象工厂模式
    如果需要创建一组相关的产品,可以将工厂方法扩展为抽象工厂模式。


总结

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

;