设计模式 - 工厂模式
01 工厂模式
背景
在写代码时,我们常常会碰到这样的情景:
- 需要根据用户输入的不同类型,创建不同的对象。比如根据配置文件中的数据库类型,创建 MySQL、PostgreSQL 或 MongoDB 的连接对象。
- 对象的创建逻辑复杂,如果散落在代码各处,会导致维护困难。
- 希望对对象的创建进行统一管理,方便添加新的产品类型。
因此,工厂模式(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;
}
优点
- 解耦:客户端代码不需要关心对象的具体创建过程
- 易于扩展:添加新产品只需修改工厂类,不影响客户端
- 统一管理:所有对象的创建都在一个地方,便于维护
变体
- 简单工厂:工厂类根据参数直接创建对象(上面的例子其实就是简单工厂)
- 工厂方法:定义一个创建对象的接口,让子类决定实例化哪个类
- 抽象工厂:提供一个创建一系列相关对象的接口,无需指定具体类
总结
工厂模式是创建型模式中最常用的模式之一,在 C++ 中尤其适用于:
- 需要根据配置创建不同对象
- 对象创建逻辑复杂
- 需要统一管理对象创建
掌握工厂模式,能让你的代码更加灵活和可维护。