抽象工厂

. 抽象工厂模式 (Abstract Factory)

代码示例:跨平台 UI 组件库

假设我们要开发一个 UI 库,支持 WindowsMac 两种风格。

  • 每种风格都有配套的:按钮 (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. 定义

  • 原文: 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
  • 解读:
    • “一系列相关对象”:这就是产品族。比如上面的 WinButtonWinCheckbox 就是一家人。
    • “无需指定具体类”:客户端只管找工厂要 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 的,不能混用。
posted @ 2025-12-20 20:43  belief73  阅读(1)  评论(0)    收藏  举报