Bootstrap

C++实现设计模式---抽象工厂模式 (Abstract Factory)

抽象工厂模式 (Abstract Factory)

抽象工厂模式 是一种创建型设计模式,提供一个接口,用于创建一组相关或互相依赖的对象,而无需指定它们的具体类。


意图

  • 提供一个创建一组相关对象的接口,而无需指定它们的具体类。
  • 解决产品对象之间的相互依赖问题,使得一组对象能协同工作。

使用场景

  1. 需要创建一组相关对象
    • 如 GUI 程序中,窗口、按钮、菜单等需要统一的外观风格。
  2. 需要保证对象之间的兼容性
    • 如游戏开发中,不同种族的士兵和建筑需要互相匹配。
  3. 需要隐藏具体实现
    • 客户端代码只依赖于产品接口,具体实现被封装。

参与者角色

  1. 抽象工厂 (Abstract Factory)
    • 声明一组用于创建相关对象的接口。
  2. 具体工厂 (Concrete Factory)
    • 实现抽象工厂的接口,创建具体的产品。
  3. 抽象产品 (Abstract Product)
    • 定义所有产品的公共接口。
  4. 具体产品 (Concrete Product)
    • 实现抽象产品的接口,为具体工厂生产的对象。

示例代码

以下示例展示了如何使用抽象工厂模式为不同操作系统创建相关的 GUI 组件(按钮和窗口)。

#include <iostream>
#include <memory>

// 抽象产品 A: 按钮
class Button {
public:
    virtual void render() const = 0;
    virtual ~Button() {}
};

// 具体产品 A1: Windows 按钮
class WindowsButton : public Button {
public:
    void render() const override {
        std::cout << "Rendering Windows Button" << std::endl;
    }
};

// 具体产品 A2: Mac 按钮
class MacButton : public Button {
public:
    void render() const override {
        std::cout << "Rendering Mac Button" << std::endl;
    }
};

// 抽象产品 B: 窗口
class Window {
public:
    virtual void render() const = 0;
    virtual ~Window() {}
};

// 具体产品 B1: Windows 窗口
class WindowsWindow : public Window {
public:
    void render() const override {
        std::cout << "Rendering Windows Window" << std::endl;
    }
};

// 具体产品 B2: Mac 窗口
class MacWindow : public Window {
public:
    void render() const override {
        std::cout << "Rendering Mac Window" << std::endl;
    }
};

// 抽象工厂
class GUIFactory {
public:
    virtual std::unique_ptr<Button> createButton() const = 0;
    virtual std::unique_ptr<Window> createWindow() const = 0;
    virtual ~GUIFactory() {}
};

// 具体工厂 1: Windows 工厂
class WindowsFactory : public GUIFactory {
public:
    std::unique_ptr<Button> createButton() const override {
        return std::make_unique<WindowsButton>();
    }

    std::unique_ptr<Window> createWindow() const override {
        return std::make_unique<WindowsWindow>();
    }
};

// 具体工厂 2: Mac 工厂
class MacFactory : public GUIFactory {
public:
    std::unique_ptr<Button> createButton() const override {
        return std::make_unique<MacButton>();
    }

    std::unique_ptr<Window> createWindow() const override {
        return std::make_unique<MacWindow>();
    }
};

// 主函数
int main() {
    // 选择具体工厂
    std::unique_ptr<GUIFactory> factory = std::make_unique<WindowsFactory>();

    // 使用工厂创建产品
    auto button = factory->createButton();
    auto window = factory->createWindow();

    button->render(); // 输出:Rendering Windows Button
    window->render(); // 输出:Rendering Windows Window

    // 切换到另一种具体工厂
    factory = std::make_unique<MacFactory>();

    button = factory->createButton();
    window = factory->createWindow();

    button->render(); // 输出:Rendering Mac Button
    window->render(); // 输出:Rendering Mac Window

    return 0;
}

代码解析

1. 抽象产品类

定义了产品的公共接口,确保产品类型的一致性:

class Button {
public:
    virtual void render() const = 0;
    virtual ~Button() {}
};

2. 具体产品类

实现了抽象产品接口,并提供具体功能:

class WindowsButton : public Button {
public:
    void render() const override {
        std::cout << "Rendering Windows Button" << std::endl;
    }
};

3. 抽象工厂

定义了创建一组相关产品的接口:

class GUIFactory {
public:
    virtual std::unique_ptr<Button> createButton() const = 0;
    virtual std::unique_ptr<Window> createWindow() const = 0;
    virtual ~GUIFactory() {}
};

4. 具体工厂

实现了抽象工厂接口,负责生产具体的产品:

class WindowsFactory : public GUIFactory {
public:
    std::unique_ptr<Button> createButton() const override {
        return std::make_unique<WindowsButton>();
    }

    std::unique_ptr<Window> createWindow() const override {
        return std::make_unique<WindowsWindow>();
    }
};

5. 主函数

客户端代码通过工厂接口创建产品,无需知道具体产品的实现:

std::unique_ptr<GUIFactory> factory = std::make_unique<WindowsFactory>();
auto button = factory->createButton();
auto window = factory->createWindow();
button->render();
window->render();

优缺点

优点

  1. 解耦:客户端代码只依赖抽象工厂和抽象产品,与具体实现无关。
  2. 保证产品一致性:抽象工厂确保一组对象是兼容的。
  3. 扩展性强:可以通过新增具体工厂扩展系统。

缺点

  1. 增加复杂性:每增加一组产品需要新增抽象类和具体类。
  2. 灵活性受限:对现有产品结构的修改可能需要更新所有工厂。

适用场景

  • 跨平台开发:如为不同操作系统设计统一的 GUI。
  • 产品族设计:如游戏中不同种族的士兵和建筑需要互相匹配。
  • 动态扩展产品族:如增加新的平台支持。

改进与扩展

  1. 结合配置文件
    动态选择具体工厂,根据运行时条件决定产品族的创建:

    std::unique_ptr<GUIFactory> factory;
    if (platform == "Windows") {
        factory = std::make_unique<WindowsFactory>();
    } else {
        factory = std::make_unique<MacFactory>();
    }
    
  2. 引入依赖注入框架
    通过依赖注入简化工厂选择的逻辑,使得代码更易于维护和测试。


总结

抽象工厂模式通过提供一个接口,用于创建一组相关对象,实现了创建逻辑的集中化和产品族之间的兼容性。
它适用于需要跨平台开发或产品族设计的场景。

;