C++设计模式之抽象工厂模式:以家具生产为例

一、抽象工厂模式的核心概念

抽象工厂模式是一种创建型设计模式,其核心作用是提供一个接口,用于创建一系列相互关联或相互依赖的对象,而无需指定它们的具体类。简单来说,它就像一个"超级工厂",这个工厂不仅能生产单一产品,还能生产一整套配套的产品系列。

我们以日常家具使用场景为例:家庭装修时,我们通常会选择同一风格的家具,比如现代简约风格的沙发+茶几,或者古典实木风格的沙发+茶几。这里的"现代风格家具厂"和"古典风格家具厂"就相当于抽象工厂模式中的具体工厂,它们各自能生产一套配套的家具产品(沙发、茶几),而"家具工厂"则是抽象工厂接口,定义了生产沙发和茶几的统一规范。

二、抽象工厂模式的核心角色

  1. 抽象工厂(Abstract Factory):定义创建一系列相关产品的接口,包含多个创建产品的纯虚函数。对应例子中的"家具工厂",定义生产"沙发"和"茶几"的接口。

  2. 具体工厂(Concrete Factory):实现抽象工厂定义的接口,负责创建某一具体风格的产品系列。对应例子中的"现代风格家具厂"和"古典风格家具厂",分别生产现代风格的沙发+茶几和古典风格的沙发+茶几。

  3. 抽象产品(Abstract Product):定义某一类产品的接口,是具体产品的父类。对应例子中的"沙发"和"茶几",各自定义了家具的基础功能(如展示风格)。

  4. 具体产品(Concrete Product):实现抽象产品的接口,是具体工厂生产的实际对象。对应例子中的"现代沙发""古典沙发""现代茶几""古典茶几",各自实现了对应风格的具体功能。

三、C++代码示例:家具生产工厂

我们通过"不同风格家具生产"的场景来实现抽象工厂模式,需求为:创建现代风格和古典风格的家具工厂,每个工厂都能生产配套的沙发和茶几,并展示家具的风格。

3.1 代码实现

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

// ---------------------- 抽象产品 ----------------------
// 抽象产品1:沙发
class Sofa {
public:
    // 纯虚函数:展示沙发风格(抽象产品的核心接口)
    virtual void showStyle() = 0;
    // 虚析构函数:确保子类对象正确析构
    virtual ~Sofa() {}
};

// 抽象产品2:茶几
class CoffeeTable {
public:
    // 纯虚函数:展示茶几风格(抽象产品的核心接口)
    virtual void showStyle() = 0;
    // 虚析构函数:确保子类对象正确析构
    virtual ~CoffeeTable() {}
};

// ---------------------- 具体产品 ----------------------
// 具体产品1.1:现代风格沙发
class ModernSofa : public Sofa {
public:
    void showStyle() override {
        cout << "这是现代风格沙发,设计简约,线条流畅" << endl;
    }
};

// 具体产品1.2:古典风格沙发
class ClassicSofa : public Sofa {
public:
    void showStyle() override {
        cout << "这是古典风格沙发,雕刻精美,材质厚重" << endl;
    }
};

// 具体产品2.1:现代风格茶几
class ModernCoffeeTable : public CoffeeTable {
public:
    void showStyle() override {
        cout << "这是现代风格茶几,玻璃台面,金属支架" << endl;
    }
};

// 具体产品2.2:古典风格茶几
class ClassicCoffeeTable : public CoffeeTable {
public:
    void showStyle() override {
        cout << "这是古典风格茶几,实木材质,雕花装饰" << endl;
    }
};

// ---------------------- 抽象工厂 ----------------------
// 抽象家具工厂:定义生产沙发和茶几的接口(产品系列)
class AbstractFurnitureFactory {
public:
    // 纯虚函数:创建沙发
    virtual Sofa* createSofa() = 0;
    // 纯虚函数:创建茶几
    virtual CoffeeTable* createCoffeeTable() = 0;
    // 虚析构函数:确保子类工厂正确析构
    virtual ~AbstractFurnitureFactory() {}
};

// ---------------------- 具体工厂 ----------------------
// 具体工厂1:现代风格家具厂(生产现代系列产品)
class ModernFurnitureFactory : public AbstractFurnitureFactory {
public:
    Sofa* createSofa() override {
        // 生产现代风格沙发
        return new ModernSofa();
    }

    CoffeeTable* createCoffeeTable() override {
        // 生产现代风格茶几(与沙发配套)
        return new ModernCoffeeTable();
    }
};

// 具体工厂2:古典风格家具厂(生产古典系列产品)
class ClassicFurnitureFactory : public AbstractFurnitureFactory {
public:
    Sofa* createSofa() override {
        // 生产古典风格沙发
        return new ClassicSofa();
    }

    CoffeeTable* createCoffeeTable() override {
        // 生产古典风格茶几(与沙发配套)
        return new ClassicCoffeeTable();
    }
};

// ---------------------- 客户端代码 ----------------------
// 客户端使用:传入具体工厂,获取配套产品并使用
void clientCode(AbstractFurnitureFactory* factory) {
    // 从工厂获取沙发和茶几(无需关心具体类型,只依赖抽象接口)
    Sofa* sofa = factory->createSofa();
    CoffeeTable* coffeeTable = factory->createCoffeeTable();

    // 使用产品(多态调用,展示对应风格)
    cout << "=== 家具套装展示 ===" << endl;
    sofa->showStyle();
    coffeeTable->showStyle();

    // 释放资源
    delete sofa;
    delete coffeeTable;
}

int main() {
    // 场景1:购买现代风格家具套装
    cout << "--- 购买现代风格家具 ---" << endl;
    AbstractFurnitureFactory* modernFactory = new ModernFurnitureFactory();
    clientCode(modernFactory);
    delete modernFactory;

    // 场景2:购买古典风格家具套装
    cout << "\n--- 购买古典风格家具 ---" << endl;
    AbstractFurnitureFactory* classicFactory = new ClassicFurnitureFactory();
    clientCode(classicFactory);
    delete classicFactory;

    return 0;
}

3.2 代码说明

  1. 抽象产品层 :定义SofaCoffeeTable两个抽象类,均包含纯虚函数showStyle(),明确了家具"展示风格"的核心功能。

  2. 具体产品层 :每个抽象产品对应两个具体实现(现代风格和古典风格),如ModernSofaClassicSofa,分别实现了不同风格的showStyle()方法。

  3. 抽象工厂层AbstractFurnitureFactory定义了创建沙发和茶几的两个纯虚函数,确保具体工厂必须生产这一套配套产品。

  4. 具体工厂层ModernFurnitureFactoryClassicFurnitureFactory分别实现了抽象工厂的接口,生产对应风格的配套家具,保证了产品系列的一致性。

  5. 客户端层clientCode()函数仅依赖抽象工厂和抽象产品接口,无需知道具体产品的创建细节。当需要更换家具风格时,只需替换具体工厂对象(如从ModernFurnitureFactory换成ClassicFurnitureFactory),无需修改客户端核心逻辑。

四、抽象工厂模式的适用场景与优缺点

4.1 适用场景

  • 需要创建一系列配套产品时,如例子中的"沙发+茶几"套装、电子设备的"手机+充电器"套装等。

  • 希望隔离产品的具体实现,客户端仅依赖抽象接口,便于后续扩展新的产品系列(如新增"北欧风格家具厂")。

  • 需要确保产品系列的一致性,避免出现"现代沙发+古典茶几"这种不配套的组合。

4.2 优点

  • 保证产品系列的一致性:具体工厂只生产配套产品,避免不兼容的产品组合。

  • 降低耦合度:客户端与具体产品解耦,仅通过抽象接口交互,符合"依赖倒置原则"。

  • 便于扩展新的产品系列:新增风格(如北欧风格)时,只需新增具体产品类和具体工厂类,无需修改现有代码,符合"开闭原则"。

4.3 缺点

  • 扩展新的产品种类成本高:若要新增产品(如在家具系列中新增"衣柜"),需修改抽象工厂接口及所有具体工厂的实现,违反"开闭原则"。

  • 类数量膨胀:每增加一个产品系列或一个产品种类,都需要新增多个类(抽象产品、具体产品、具体工厂),导致系统类结构复杂。

五、总结

抽象工厂模式是解决"配套产品创建"问题的核心模式,通过抽象工厂定义产品系列的创建规范,具体工厂实现某一风格的产品生产,客户端依赖抽象接口实现解耦。在日常开发中,当遇到"一系列相互关联的产品需要统一创建"的场景(如UI组件库、设备驱动套件等),抽象工厂模式会是理想的选择。但需注意其"扩展产品种类成本高"的局限性,在设计时需合理规划产品系列的范围。

相关推荐
旖旎夜光1 小时前
list实现(7)(下)
c++·list
jwybobo20072 小时前
redis7.x源码分析:(9) 内存淘汰策略
linux·c++·redis
阿拉伯柠檬2 小时前
实现一个异步操作线程池
开发语言·数据结构·c++·面试
2301_803554522 小时前
Qt禁止子线程直接操作GUI
c++
阿波罗尼亚2 小时前
Head First设计模式(十一) 设计原则 代理模式
设计模式·代理模式
羑悻的小杀马特2 小时前
C++与Redis高效交互:通过optional与迭代器玩转String/List/Set......,打造高性能存储方案!
c++·redis·交互
+++.3 小时前
c++雪花屏(vsCode+cmake+mingw+ninja)
开发语言·c++·vscode
小年糕是糕手3 小时前
【C++】内存管理(下)
java·c语言·开发语言·数据结构·c++·算法
一叶之秋14123 小时前
深入剖析vector的底层实现原理
c++