代码示例:跨平台 UI 组件库
假设我们要开发一个 UI 库,支持 Windows 和 Mac 两种风格。
-
每种风格都有配套的:按钮 (Button) 和 复选框 (Checkbox)。
-
规则: Windows 的按钮必须搭配 Windows 的复选框,绝对不能混搭(防止风格不统一)。
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. 什么时候用?
当你需要强行约束“对象必须配套使用”的时候。
-
例如:
-
游戏开发: 换皮肤。一套皮肤里包含(角色模型、武器模型、特效音效)。你不能穿“关羽”的衣服,拿“孙悟空”的棒子。
-
数据库切换:
-