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组件库、设备驱动套件等),抽象工厂模式会是理想的选择。但需注意其"扩展产品种类成本高"的局限性,在设计时需合理规划产品系列的范围。

相关推荐
小尧嵌入式5 分钟前
C++选择排序插入排序希尔排序快排归并排及大小根堆实现优先级队列
数据结构·c++·windows·算法·排序算法
程序员泠零澪回家种桔子7 分钟前
ReAct Agent 后端架构解析
后端·spring·设计模式·架构
Dream it possible!22 分钟前
LeetCode 面试经典 150_分治_合并 K 个升序链表(108_23_C++_困难)
c++·leetcode·链表·面试·分治
天赐学c语言23 分钟前
12.29 - 字符串相加 && vector和map的区别
数据结构·c++·算法·leecode
yuuki23323328 分钟前
【C++】 list 实现:双向循环链表解析
c++·链表·list
随意起个昵称42 分钟前
【做题总结】顺子(双指针)
c++·算法
郝学胜-神的一滴1 小时前
Linux多线程编程:深入解析pthread_detach函数
linux·服务器·开发语言·c++·程序人生
阿闽ooo1 小时前
深入浅出享元模式:从图形编辑器看对象复用的艺术
c++·设计模式·编辑器·享元模式
海盗猫鸥1 小时前
「C++」多态
开发语言·c++
MSTcheng.1 小时前
【C++】平衡树优化实战:如何手搓一棵查找更快的 AVL 树?
开发语言·数据结构·c++·avl