01 工厂模式

背景

在写代码时,我们常常会碰到这样的情景:

  1. 需要根据用户输入的不同类型,创建不同的对象。比如根据配置文件中的数据库类型,创建 MySQL、PostgreSQL 或 MongoDB 的连接对象。
  2. 对象的创建逻辑复杂,如果散落在代码各处,会导致维护困难。
  3. 希望对对象的创建进行统一管理,方便添加新的产品类型。

因此,工厂模式(Factory Pattern)就应运而生了。

分析

工厂模式的核心思想是:将对象的创建与使用分离

下面是它的 UML 图:

classDiagram
    class Product {
        <>
        +operation()
    }
    class ConcreteProductA {
        +operation()
    }
    class ConcreteProductB {
        +operation()
    }
    class Creator {
        +factoryMethod() Product
    }
    class ConcreteCreatorA {
        +factoryMethod() Product
    }
    class ConcreteCreatorB {
        +factoryMethod() Product
    }
    
    Product <|.. ConcreteProductA
    Product <|.. ConcreteProductB
    Creator <|.. ConcreteCreatorA
    Creator <|.. ConcreteCreatorB
    Creator ..> Product

例子

在 C++ 中,工厂模式非常常用。下面是一个简单的例子:

1. 定义产品接口

class Database {
public:
    virtual ~Database() = default;
    virtual void connect() = 0;
    virtual void query(const std::string& sql) = 0;
};

2. 实现具体产品

class MySQL : public Database {
public:
    void connect() override {
        std::cout << "Connecting to MySQL..." << std::endl;
    }
    void query(const std::string& sql) override {
        std::cout << "MySQL executing: " << sql << std::endl;
    }
};

class PostgreSQL : public Database {
public:
    void connect() override {
        std::cout << "Connecting to PostgreSQL..." << std::endl;
    }
    void query(const std::string& sql) override {
        std::cout << "PostgreSQL executing: " << sql << std::endl;
    }
};

3. 定义工厂

class DatabaseFactory {
public:
    enum class Type {
        MySQL,
        PostgreSQL
    };
    
    static std::unique_ptr<Database> create(Type type) {
        switch (type) {
            case Type::MySQL:
                return std::make_unique<MySQL>();
            case Type::PostgreSQL:
                return std::make_unique<PostgreSQL>();
            default:
                return nullptr;
        }
    }
};

4. 使用

int main() {
    auto db = DatabaseFactory::create(DatabaseFactory::Type::MySQL);
    db->connect();
    db->query("SELECT * FROM users");
    
    return 0;
}

优点

  1. 解耦:客户端代码不需要关心对象的具体创建过程
  2. 易于扩展:添加新产品只需修改工厂类,不影响客户端
  3. 统一管理:所有对象的创建都在一个地方,便于维护

变体

  1. 简单工厂:工厂类根据参数直接创建对象(上面的例子其实就是简单工厂)
  2. 工厂方法:定义一个创建对象的接口,让子类决定实例化哪个类
  3. 抽象工厂:提供一个创建一系列相关对象的接口,无需指定具体类

总结

工厂模式是创建型模式中最常用的模式之一,在 C++ 中尤其适用于:

  • 需要根据配置创建不同对象
  • 对象创建逻辑复杂
  • 需要统一管理对象创建

掌握工厂模式,能让你的代码更加灵活和可维护。