工厂模式(Factory Pattern)是C++中常用的设计模式之一,它属于创建型模式,提供了一种创建对象的最佳方式,而无需将对象创建的逻辑暴露给客户端。工厂模式的主要目的是定义一个用于创建对象的接口,但让子类决定实例化哪一个类。这样,工厂方法使一个类的实例化延迟到其子类。工厂模式可以进一步分为简单工厂模式、工厂方法模式和抽象工厂模式三种类型。
工厂模式的三种形式
1. 简单工厂模式(Simple Factory)
简单工厂模式并不是GoF定义的23种设计模式之一,但它是理解工厂模式的基础。
#include <iostream>
#include <memory>
// 产品接口
class Product {
public:
virtual ~Product() = default;
virtual void operation() = 0;
};
// 具体产品A
class ConcreteProductA : public Product {
public:
void operation() override {
std::cout << "ConcreteProductA operation" << std::endl;
}
};
// 具体产品B
class ConcreteProductB : public Product {
public:
void operation() override {
std::cout << "ConcreteProductB operation" << std::endl;
}
};
// 简单工厂
class SimpleFactory {
public:
enum ProductType { A, B };
static std::unique_ptr<Product> createProduct(ProductType type) {
switch (type) {
case A: return std::make_unique<ConcreteProductA>();
case B: return std::make_unique<ConcreteProductB>();
default: return nullptr;
}
}
};
int main() {
auto productA = SimpleFactory::createProduct(SimpleFactory::A);
productA->operation(); // 输出: ConcreteProductA operation
auto productB = SimpleFactory::createProduct(SimpleFactory::B);
productB->operation(); // 输出: ConcreteProductB operation
return 0;
}
2. 工厂方法模式(Factory Method)
工厂方法模式定义了一个创建对象的接口,但让子类决定实例化哪一个类。
#include <iostream>
#include <memory>
// 产品接口
class Product {
public:
virtual ~Product() = default;
virtual void operation() = 0;
};
// 具体产品A
class ConcreteProductA : public Product {
public:
void operation() override {
std::cout << "ConcreteProductA operation" << std::endl;
}
};
// 具体产品B
class ConcreteProductB : public Product {
public:
void operation() override {
std::cout << "ConcreteProductB operation" << std::endl;
}
};
// 工厂接口
class Factory {
public:
virtual ~Factory() = default;
virtual std::unique_ptr<Product> createProduct() = 0;
};
// 具体工厂A
class ConcreteFactoryA : public Factory {
public:
std::unique_ptr<Product> createProduct() override {
return std::make_unique<ConcreteProductA>();
}
};
// 具体工厂B
class ConcreteFactoryB : public Factory {
public:
std::unique_ptr<Product> createProduct() override {
return std::make_unique<ConcreteProductB>();
}
};
int main() {
std::unique_ptr<Factory> factoryA = std::make_unique<ConcreteFactoryA>();
auto productA = factoryA->createProduct();
productA->operation(); // 输出: ConcreteProductA operation
std::unique_ptr<Factory> factoryB = std::make_unique<ConcreteFactoryB>();
auto productB = factoryB->createProduct();
productB->operation(); // 输出: ConcreteProductB operation
return 0;
}
3. 抽象工厂模式(Abstract Factory)
抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
#include <iostream>
#include <memory>
// 抽象产品A
class AbstractProductA {
public:
virtual ~AbstractProductA() = default;
virtual void operationA() = 0;
};
// 具体产品A1
class ProductA1 : public AbstractProductA {
public:
void operationA() override {
std::cout << "ProductA1 operationA" << std::endl;
}
};
// 具体产品A2
class ProductA2 : public AbstractProductA {
public:
void operationA() override {
std::cout << "ProductA2 operationA" << std::endl;
}
};
// 抽象产品B
class AbstractProductB {
public:
virtual ~AbstractProductB() = default;
virtual void operationB() = 0;
};
// 具体产品B1
class ProductB1 : public AbstractProductB {
public:
void operationB() override {
std::cout << "ProductB1 operationB" << std::endl;
}
};
// 具体产品B2
class ProductB2 : public AbstractProductB {
public:
void operationB() override {
std::cout << "ProductB2 operationB" << std::endl;
}
};
// 抽象工厂
class AbstractFactory {
public:
virtual ~AbstractFactory() = default;
virtual std::unique_ptr<AbstractProductA> createProductA() = 0;
virtual std::unique_ptr<AbstractProductB> createProductB() = 0;
};
// 具体工厂1
class ConcreteFactory1 : public AbstractFactory {
public:
std::unique_ptr<AbstractProductA> createProductA() override {
return std::make_unique<ProductA1>();
}
std::unique_ptr<AbstractProductB> createProductB() override {
return std::make_unique<ProductB1>();
}
};
// 具体工厂2
class ConcreteFactory2 : public AbstractFactory {
public:
std::unique_ptr<AbstractProductA> createProductA() override {
return std::make_unique<ProductA2>();
}
std::unique_ptr<AbstractProductB> createProductB() override {
return std::make_unique<ProductB2>();
}
};
int main() {
std::unique_ptr<AbstractFactory> factory1 = std::make_unique<ConcreteFactory1>();
auto productA1 = factory1->createProductA();
auto productB1 = factory1->createProductB();
productA1->operationA(); // 输出: ProductA1 operationA
productB1->operationB(); // 输出: ProductB1 operationB
std::unique_ptr<AbstractFactory> factory2 = std::make_unique<ConcreteFactory2>();
auto productA2 = factory2->createProductA();
auto productB2 = factory2->createProductB();
productA2->operationA(); // 输出: ProductA2 operationA
productB2->operationB(); // 输出: ProductB2 operationB
return 0;
}
实际案例:数据库连接管理
通过数据库连接这个实际场景,详细分析三种模式的实现和区别。假设我们需要开发一个支持多种数据库(MySQL、PostgreSQL、SQLite)的连接管理系统。
1. 简单工厂模式实现
#include <iostream>
#include <memory>
#include <string>
// 数据库连接接口
class DatabaseConnection {
public:
virtual ~DatabaseConnection() = default;
virtual void connect() = 0;
virtual void executeQuery(const std::string& query) = 0;
};
// MySQL连接
class MySQLConnection : public DatabaseConnection {
public:
void connect() override {
std::cout << "Connected to MySQL database" << std::endl;
}
void executeQuery(const std::string& query) override {
std::cout << "Executing MySQL query: " << query << std::endl;
}
};
// PostgreSQL连接
class PostgreSQLConnection : public DatabaseConnection {
public:
void connect() override {
std::cout << "Connected to PostgreSQL database" << std::endl;
}
void executeQuery(const std::string& query) override {
std::cout << "Executing PostgreSQL query: " << query << std::endl;
}
};
// 简单数据库工厂
class DatabaseFactory {
public:
enum DBType { MYSQL, POSTGRESQL };
static std::unique_ptr<DatabaseConnection> createConnection(DBType type) {
switch (type) {
case MYSQL: return std::make_unique<MySQLConnection>();
case POSTGRESQL: return std::make_unique<PostgreSQLConnection>();
default: throw std::invalid_argument("Unknown database type");
}
}
};
// 客户端代码
int main() {
auto mysqlConn = DatabaseFactory::createConnection(DatabaseFactory::MYSQL);
mysqlConn->connect();
mysqlConn->executeQuery("SELECT * FROM users");
auto pgConn = DatabaseFactory::createConnection(DatabaseFactory::POSTGRESQL);
pgConn->connect();
pgConn->executeQuery("SELECT * FROM customers");
return 0;
}
简单工厂特点分析:
-
一个工厂类负责所有产品的创建
-
通过参数判断创建哪种产品
-
新增数据库类型需要修改工厂类(违反开闭原则)
-
适用于产品较少且不常变化的场景
2. 工厂方法模式实现
// 前面DatabaseConnection及其子类定义不变...
// 抽象工厂接口
class DatabaseFactory {
public:
virtual ~DatabaseFactory() = default;
virtual std::unique_ptr<DatabaseConnection> createConnection() = 0;
};
// MySQL工厂
class MySQLFactory : public DatabaseFactory {
public:
std::unique_ptr<DatabaseConnection> createConnection() override {
return std::make_unique<MySQLConnection>();
}
};
// PostgreSQL工厂
class PostgreSQLFactory : public DatabaseFactory {
public:
std::unique_ptr<DatabaseConnection> createConnection() override {
return std::make_unique<PostgreSQLConnection>();
}
};
// 新增SQLite支持不需要修改已有代码
class SQLiteConnection : public DatabaseConnection {
public:
void connect() override {
std::cout << "Connected to SQLite database" << std::endl;
}
void executeQuery(const std::string& query) override {
std::cout << "Executing SQLite query: " << query << std::endl;
}
};
class SQLiteFactory : public DatabaseFactory {
public:
std::unique_ptr<DatabaseConnection> createConnection() override {
return std::make_unique<SQLiteConnection>();
}
};
// 客户端代码
void clientCode(DatabaseFactory& factory) {
auto conn = factory.createConnection();
conn->connect();
conn->executeQuery("SELECT * FROM products");
}
int main() {
MySQLFactory mysqlFactory;
clientCode(mysqlFactory);
PostgreSQLFactory pgFactory;
clientCode(pgFactory);
SQLiteFactory sqliteFactory;
clientCode(sqliteFactory);
return 0;
}
工厂方法特点分析:
-
每个产品对应一个具体工厂类
-
新增数据库类型只需添加新工厂类(符合开闭原则)
-
客户端依赖抽象工厂接口,不依赖具体类
-
适合产品类型可能扩展的场景
3. 抽象工厂模式实现
现在需求升级:除了数据库连接,还需要支持不同数据库的数据迁移工具。
// 数据库连接接口及实现同上...
// 数据迁移工具接口
class DataMigrationTool {
public:
virtual ~DataMigrationTool() = default;
virtual void migrate(const std::string& table) = 0;
};
// MySQL迁移工具
class MySQLMigrationTool : public DataMigrationTool {
public:
void migrate(const std::string& table) override {
std::cout << "Migrating MySQL table: " << table << std::endl;
}
};
// PostgreSQL迁移工具
class PostgreSQLMigrationTool : public DataMigrationTool {
public:
void migrate(const std::string& table) override {
std::cout << "Migrating PostgreSQL table: " << table << std::endl;
}
};
// 抽象工厂接口
class DatabaseFactory {
public:
virtual ~DatabaseFactory() = default;
virtual std::unique_ptr<DatabaseConnection> createConnection() = 0;
virtual std::unique_ptr<DataMigrationTool> createMigrationTool() = 0;
};
// MySQL产品族工厂
class MySQLFactory : public DatabaseFactory {
public:
std::unique_ptr<DatabaseConnection> createConnection() override {
return std::make_unique<MySQLConnection>();
}
std::unique_ptr<DataMigrationTool> createMigrationTool() override {
return std::make_unique<MySQLMigrationTool>();
}
};
// PostgreSQL产品族工厂
class PostgreSQLFactory : public DatabaseFactory {
public:
std::unique_ptr<DatabaseConnection> createConnection() override {
return std::make_unique<PostgreSQLConnection>();
}
std::unique_ptr<DataMigrationTool> createMigrationTool() override {
return std::make_unique<PostgreSQLMigrationTool>();
}
};
// 客户端代码
void clientCode(DatabaseFactory& factory) {
auto conn = factory.createConnection();
auto tool = factory.createMigrationTool();
conn->connect();
conn->executeQuery("SELECT * FROM products");
tool->migrate("users");
}
int main() {
MySQLFactory mysqlFactory;
clientCode(mysqlFactory);
PostgreSQLFactory pgFactory;
clientCode(pgFactory);
return 0;
}
抽象工厂特点分析:
-
创建的是产品族(多个相关产品)
-
每个具体工厂负责创建一组相关产品
-
保证产品之间的兼容性
-
适合需要创建多个相关对象的复杂系统
三者的核心区别总结
特性 | 简单工厂模式 | 工厂方法模式 | 抽象工厂模式 |
---|---|---|---|
工厂角色 | 一个具体工厂类 | 多个具体工厂类 | 多个具体工厂类(产品族工厂) |
扩展性 | 修改工厂类(违反开闭原则) | 新增工厂类(符合开闭原则) | 新增产品族工厂(符合开闭原则) |
创建目标 | 单一产品 | 单一产品 | 产品族(多个相关产品) |
适用场景 | 产品类型固定的小型系统 | 需要灵活扩展产品的系统 | 需要保证产品兼容性的复杂系统 |
复杂度 | 简单 | 中等 | 较高 |
产品间约束 | 无 | 无 | 有(保证产品族兼容性) |
选择建议
-
如果产品类型固定不变且数量少 → 简单工厂
-
如果产品类型可能扩展 → 工厂方法
-
如果需要创建多个相关产品对象(产品族)→ 抽象工厂
-
在大型系统中,三种模式可能组合使用
工厂方法模式是抽象工厂模式的基础,而抽象工厂模式通常包含多个工厂方法。理解这些差异可以帮助你在实际开发中选择最合适的模式。
工厂模式的应用场景
-
简单工厂模式:
-
当对象的创建逻辑比较简单时
-
客户端不需要知道具体的产品类名
-
-
工厂方法模式:
-
当一个类不知道它所需要的对象的类时
-
当一个类希望由它的子类来指定它所创建的对象时
-
当将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化时
-
-
抽象工厂模式:
-
系统需要独立于它的产品的创建、组合和表示时
-
系统需要由多个产品系列中的一个来配置时
-
当需要强调一系列相关的产品对象的设计以便进行联合使用时
-
当提供一个产品类库,而只想显示它们的接口而不是实现时
-
工厂模式的优点
-
封装性好:客户端不需要知道具体产品类的类名,只需要知道工厂类即可
-
扩展性好:增加新的产品时,只需要扩展一个工厂类即可
-
解耦:工厂模式将对象的创建与使用分离
-
符合开闭原则:对扩展开放,对修改关闭
工厂模式的缺点
-
增加复杂度:每增加一个产品,就需要增加一个具体产品类和工厂类
-
抽象性增加:引入了抽象层,增加了系统的抽象性和理解难度
-
具体产品与工厂耦合:工厂方法模式中,具体产品与具体工厂一一对应
工厂模式是C++中非常常用的设计模式,特别是在需要灵活创建对象的场景中。理解并合理运用工厂模式,可以大大提高代码的可维护性和扩展性。