抽象工厂
. 抽象工厂模式 (Abstract Factory)
代码示例:跨平台 UI 组件库
假设我们要开发一个 UI 库,支持 Windows 和 Mac 两种风格。
- 每种风格都有配套的:按钮 (Button) 和 复选框 (Checkbox)。
- 规则: Windows 的按钮必须搭配 Windows 的复选框,绝对不能混搭(防止风格不统一)。
#include <iostream>
#include <string>
using namespace std;
// ==========================================
// 1. 抽象产品族 (Abstract Products)
// 稳定点:无论哪个系统,都有按钮和复选框
// ==========================================
class IButton {
public:
virtual ~IButton() {}
virtual void Click() = 0;
};
class ICheckbox {
public:
virtual ~ICheckbox() {}
virtual void Check() = 0;
};
// ==========================================
// 2. 具体产品 (Concrete Products)
// 变化点:不同系统的具体实现
// ==========================================
// --- Windows 系列 ---
class WinButton : public IButton {
public:
void Click() override { cout << " [Win] 绘制方形按钮" << endl; }
};
class WinCheckbox : public ICheckbox {
public:
void Check() override { cout << " [Win] 绘制方框打钩" << endl; }
};
// --- Mac 系列 ---
class MacButton : public IButton {
public:
void Click() override { cout << " [Mac] 绘制圆角按钮" << endl; }
};
class MacCheckbox : public ICheckbox {
public:
void Check() override { cout << " [Mac] 绘制圆形选中" << endl; }
};
// ==========================================
// 3. 抽象工厂 (Abstract Factory)
// 稳定点:工厂必须能生产“一套”组件
// 核心区别:工厂方法只有一个 Create,这里有多个 Create
// ==========================================
class IGUIFactory {
public:
virtual ~IGUIFactory() {}
virtual IButton* CreateButton() = 0;
virtual ICheckbox* CreateCheckbox() = 0;
};
// ==========================================
// 4. 具体工厂 (Concrete Factories)
// 变化点:每个工厂负责生产“一个系列”
// ==========================================
class WinFactory : public IGUIFactory {
public:
IButton* CreateButton() override { return new WinButton(); }
ICheckbox* CreateCheckbox() override { return new WinCheckbox(); }
};
class MacFactory : public IGUIFactory {
public:
IButton* CreateButton() override { return new MacButton(); }
ICheckbox* CreateCheckbox() override { return new MacCheckbox(); }
};
// ==========================================
// 客户端代码 (Client)
// ==========================================
// 业务逻辑:渲染一个表单
// 关键:它只知道 IGUIFactory,完全不知道是 Windows 还是 Mac
void RenderForm(IGUIFactory* factory) {
cout << "--- 开始渲染表单 ---" << endl;
IButton* btn = factory->CreateButton();
ICheckbox* box = factory->CreateCheckbox();
btn->Click();
box->Check();
// 确保了 btn 和 box 是一家的,不会出现 WinButton 配 MacCheckbox
delete btn;
delete box;
}
int main() {
cout << "=== 用户配置:使用 Windows 主题 ===" << endl;
IGUIFactory* winFactory = new WinFactory();
RenderForm(winFactory);
delete winFactory;
cout << "\n=== 用户配置:使用 Mac 主题 ===" << endl;
IGUIFactory* macFactory = new MacFactory();
RenderForm(macFactory);
delete macFactory;
return 0;
}
1. 定义
- 原文: 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
- 解读:
- “一系列相关对象”:这就是产品族。比如上面的
WinButton和WinCheckbox就是一家人。 - “无需指定具体类”:客户端只管找工厂要 Button,工厂会保证给你的是配套的那一款。
- “一系列相关对象”:这就是产品族。比如上面的
2. 解决的问题 (Stable vs. Changing)
这里解决的是“多维度对象组合”的问题。
- 稳定点 (Stable):产品的种类
- UI 界面一定有按钮、文本框、复选框。这几样东西是不变的。
- 变化点 (Changing):产品的风格系列
- 可能是 Windows 风格,可能是 Mac 风格,也可能是 Linux 风格。
3. 与工厂方法模式的区别 (核心!)
这是一个常见的面试题,请务必区分:
- 工厂方法模式 (Factory Method):
- 关注点: 生产一个产品。
- 维度: 一维。
- 例子:
Logger工厂,只生产Logger。
- 抽象工厂模式 (Abstract Factory):
- 关注点: 生产一系列(配套)产品。
- 维度: 二维(产品种类 x 风格系列)。
- 例子:
GUI工厂,既生产Button又生产Checkbox。
4. 符合哪些设计原则?
- A. 依赖倒置原则 (DIP)
- 客户端只依赖
IButton,IGUIFactory等抽象接口。
- 客户端只依赖
- B. 开闭原则 (OCP) —— 有条件的符合
- 对于“增加新系列”是开放的: 如果你要加一个
Linux风格,只需要加LinuxButton,LinuxCheckbox,LinuxFactory。不需要修改现有代码。 - 对于“增加新产品”是关闭的(这是一个缺点): 如果你要在 GUI 里加一个“进度条 (Slider)”,你需要修改
IGUIFactory接口(加CreateSlider),然后所有的具体工厂(WinFactory, MacFactory)全都要改。
- 对于“增加新系列”是开放的: 如果你要加一个
5. 什么时候用?
当你需要强行约束“对象必须配套使用”的时候。
- 例如:
- 游戏开发: 换皮肤。一套皮肤里包含(角色模型、武器模型、特效音效)。你不能穿“关羽”的衣服,拿“孙悟空”的棒子。
- 数据库切换: 如果你的系统支持 MySQL 和 Oracle。Connection, Command, Cursor 这三个对象必须全是 MySQL 的,不能混用。
浙公网安备 33010602011771号