设计模式(C++)详解—抽象工厂模式 (Abstract Factory)(1)
抽象工厂模式 (Abstract Factory) 详解
背景与核心概念
抽象工厂模式是一种创建型设计模式,诞生于软件工程中对对象创建灵活性和系统可维护性的需求。该模式最早在1994年的《设计模式:可复用面向对象软件的基础》一书中被正式提出,是工厂方法模式的进一步抽象。
发展脉络
- 简单工厂阶段:最初通过一个工厂类根据参数创建不同对象
- 工厂方法阶段:为每种产品定义一个工厂接口,解决简单工厂的扩展性问题
- 抽象工厂阶段:进一步抽象,创建产品家族而非单个产品
关键术语
- 抽象工厂 (Abstract Factory):声明创建抽象产品对象的接口
- 具体工厂 (Concrete Factory):实现抽象工厂接口,创建具体产品对象
- 抽象产品 (Abstract Product):声明产品对象的接口
- 具体产品 (Concrete Product):实现抽象产品接口,定义具体产品
- 产品族 (Product Family):一组相关或依赖的产品对象
设计意图与考量
核心目标
- 封装创建逻辑:将对象创建过程封装在工厂中,客户端无需关心具体实现
- 解耦客户端与具体类:客户端只与抽象接口交互,降低系统耦合度
- 支持产品族一致性:确保创建的产品相互兼容,属于同一产品族
- 便于产品族切换:通过更换具体工厂,可以轻松切换整个产品族
设计考量
考量因素 | 说明 | 解决方案 |
---|---|---|
扩展性 | 新增产品族容易,新增产品种类困难 | 通过定义新的具体工厂支持新产品族 |
一致性 | 确保创建的产品相互兼容 | 同一工厂创建的产品属于同一产品族 |
复杂性 | 引入大量接口和类 | 权衡模式带来的好处与增加的复杂度 |
开闭原则 | 对扩展开放,对修改关闭 | 新增产品族无需修改现有代码 |
实例与应用场景
示例1:跨平台GUI组件库
// 抽象产品:按钮
class Button {
public:virtual void render() = 0;virtual void onClick() = 0;virtual ~Button() {}
};// 抽象产品:文本框
class TextBox {
public:virtual void render() = 0;virtual void onInput() = 0;virtual ~TextBox() {}
};// 具体产品:Windows按钮
class WindowsButton : public Button {
public:void render() override {std::cout << "渲染Windows风格按钮" << std::endl;}void onClick() override {std::cout << "Windows按钮点击事件处理" << std::endl;}
};// 具体产品:Windows文本框
class WindowsTextBox : public TextBox {
public:void render() override {std::cout << "渲染Windows风格文本框" << std::endl;}void onInput() override {std::cout << "Windows文本框输入事件处理" << std::endl;}
};// 具体产品:Mac按钮
class MacButton : public Button {
public:void render() override {std::cout << "渲染Mac风格按钮" << std::endl;}void onClick() override {std::cout << "Mac按钮点击事件处理" << std::endl;}
};// 具体产品:Mac文本框
class MacTextBox : public TextBox {
public:void render() override {std::cout << "渲染Mac风格文本框" << std::endl;}void onInput() override {std::cout << "Mac文本框输入事件处理" << std::endl;}
};// 抽象工厂
class GUIFactory {
public:virtual Button* createButton() = 0;virtual TextBox* createTextBox() = 0;virtual ~GUIFactory() {}
};// 具体工厂:Windows工厂
class WindowsFactory : public GUIFactory {
public:Button* createButton() override {return new WindowsButton();}TextBox* createTextBox() override {return new WindowsTextBox();}
};// 具体工厂:Mac工厂
class MacFactory : public GUIFactory {
public:Button* createButton() override {return new MacButton();}TextBox* createTextBox() override {return new MacTextBox();}
};// 客户端代码
class Application {
private:GUIFactory* factory;Button* button;TextBox* textBox;public:Application(GUIFactory* factory) : factory(factory), button(nullptr), textBox(nullptr) {}void createUI() {button = factory->createButton();textBox = factory->createTextBox();}void render() {if (button) button->render();if (textBox) textBox->render();}~Application() {delete button;delete textBox;delete factory;}
};// 使用示例
int main() {// 根据当前操作系统选择工厂GUIFactory* factory;#ifdef _WIN32factory = new WindowsFactory();#elif __APPLE__factory = new MacFactory();#endifApplication app(factory);app.createUI();app.render();return 0;
}
示例2:数据库访问抽象工厂
// 抽象产品:数据库连接
class DatabaseConnection {
public:virtual void connect() = 0;virtual void disconnect() = 0;virtual void executeQuery(const std::string& query) = 0;virtual ~DatabaseConnection() {}
};// 抽象产品:数据库命令
class DatabaseCommand {
public:virtual void setConnection(DatabaseConnection* connection) = 0;virtual void execute() = 0;virtual ~DatabaseCommand() {}
};// 具体产品:MySQL连接
class MySQLConnection : public DatabaseConnection {
public:void connect() override {std::cout << "连接到MySQL数据库" << std::endl;}void disconnect() override {std::cout << "断开MySQL数据库连接" << std::endl;}void executeQuery(const std::string& query) override {std::cout << "执行MySQL查询: " << query << std::endl;}
};// 具体产品:MySQL命令
class MySQLCommand : public DatabaseCommand {
private:DatabaseConnection* connection;public:void setConnection(DatabaseConnection* conn) override {connection = conn;}void execute() override {if (connection) {std::cout << "执行MySQL命令" << std::endl;connection->executeQuery("SELECT * FROM users");}}
};// 具体产品:PostgreSQL连接
class PostgreSQLConnection : public DatabaseConnection {
public:void connect() override {std::cout << "连接到PostgreSQL数据库" << std::endl;}void disconnect() override {std::cout << "断开PostgreSQL数据库连接" << std::endl;}void executeQuery(const std::string& query) override {std::cout << "执行PostgreSQL查询: " << query << std::endl;}
};// 具体产品:PostgreSQL命令
class PostgreSQLCommand : public DatabaseCommand {
private:DatabaseConnection* connection;public:void setConnection(DatabaseConnection* conn) override {connection = conn;}void execute() override {if (connection) {std::cout << "执行PostgreSQL命令" << std::endl;connection->executeQuery("SELECT * FROM users");}}
};// 抽象工厂
class DatabaseFactory {
public:virtual DatabaseConnection* createConnection() = 0;virtual DatabaseCommand* createCommand() = 0;virtual ~DatabaseFactory() {}
};// 具体工厂:MySQL工厂
class MySQLFactory : public DatabaseFactory {
public:DatabaseConnection* createConnection() override {return new MySQLConnection();}DatabaseCommand* createCommand() override {return new MySQLCommand();}
};// 具体工厂:PostgreSQL工厂
class PostgreSQLFactory : public DatabaseFactory {
public:DatabaseConnection* createConnection() override {return new PostgreSQLConnection();}DatabaseCommand* createCommand() override {return new PostgreSQLCommand();}
};// 客户端代码
class DatabaseClient {
private:DatabaseFactory* factory;DatabaseConnection* connection;DatabaseCommand* command;public:DatabaseClient(DatabaseFactory* dbFactory) : factory(dbFactory), connection(nullptr), command(nullptr) {}void initialize() {connection = factory->createConnection();command = factory->createCommand();connection->connect();command->setConnection(connection);}void performOperation() {if (command) {command->execute();}}~DatabaseClient() {if (connection) {connection->disconnect();delete connection;}delete command;delete factory;}
};// 使用示例
int main() {// 根据配置选择数据库类型std::string dbType = "MySQL"; // 可以从配置文件读取DatabaseFactory* factory;if (dbType == "MySQL") {factory = new MySQLFactory();} else if (dbType == "PostgreSQL") {factory = new PostgreSQLFactory();} else {throw std::runtime_error("不支持的数据库类型");}DatabaseClient client(factory);client.initialize();client.performOperation();return 0;
}
编译与运行
创建以下Makefile文件:
CXX = g++
CXXFLAGS = -std=c++11 -Wallall: gui_example db_examplegui_example: gui_example.cpp$(CXX) $(CXXFLAGS) -o gui_example gui_example.cppdb_example: db_example.cpp$(CXX) $(CXXFLAGS) -o db_example db_example.cppclean:rm -f gui_example db_example.PHONY: all clean
编译和运行:
# 编译
make# 运行GUI示例
./gui_example# 运行数据库示例
./db_example
交互性内容解析
抽象工厂模式的时序图
模式参与者交互说明
- 客户端 (Client):仅与抽象工厂和抽象产品接口交互
- 抽象工厂 (AbstractFactory):声明创建抽象产品的接口
- 具体工厂 (ConcreteFactory):实现抽象工厂接口,创建具体产品
- 抽象产品 (AbstractProduct):声明产品对象的接口
- 具体产品 (ConcreteProduct):实现抽象产品接口,定义具体产品
这种交互方式确保了客户端代码与具体产品类的实现解耦,提高了代码的灵活性和可维护性。
图示化呈现
抽象工厂模式类图
模式结构说明
- 抽象工厂:定义创建抽象产品对象的接口
- 具体工厂:实现抽象工厂接口,创建具体产品对象
- 抽象产品:为产品对象声明接口
- 具体产品:实现抽象产品接口,定义具体产品
这种结构确保了:
- 客户端与具体产品类解耦
- 产品族一致性(同一工厂创建的产品相互兼容)
- 易于切换产品族(只需更换具体工厂)
总结
抽象工厂模式是一种强大的创建型设计模式,特别适用于需要创建相关或依赖对象家族的场景。通过将对象创建过程抽象化,该模式实现了客户端代码与具体产品类的解耦,提高了系统的灵活性和可维护性。
模式优势
- 产品族一致性:确保创建的产品相互兼容
- 客户端与具体类解耦:客户端只与抽象接口交互
- 易于切换产品族:通过更换具体工厂即可切换整个产品族
- 符合开闭原则:新增产品族无需修改现有代码
适用场景
- 跨平台应用:为不同操作系统创建相应的UI组件
- 数据库访问:支持多种数据库系统,保持接口一致
- 主题系统:为应用程序提供可切换的视觉主题
- 游戏开发:为不同游戏风格创建相应的角色、道具等
注意事项
- 扩展产品种类困难:新增产品种类需要修改所有工厂类
- 增加了系统复杂度:引入了大量接口和类
- 理解难度较高:相对于简单工厂模式,抽象工厂模式更加复杂
在实际应用中,需要根据具体需求权衡是否使用抽象工厂模式。对于需要创建相关对象家族且需要保持产品一致性的场景,抽象工厂模式是一个优秀的选择。