C++设计模式——Abstract Factory Pattern抽象工厂模式

一、抽象工厂模式的定义

抽象工厂模式是一种创建型设计模式,它提供了一种将相关/依赖对象组合在一起创建的方式,而无需指定它们的具体类。

抽象工厂模式与工厂方法模式的区别:

工厂方法模式将对象的创建过程延迟到子类中,允许用户通过一个统一的接口来请求他们想要的具体产品,而无需知道产品的具体实现。在这个模式中,工厂类只负责生产同一系列的产品,但具体哪种产品由子类决定。

抽象工厂模式更进一步,它提供了一个接口,用于创建一系列相关的或相互依赖的对象,而不是单一对象。抽象工厂封装了产品系列的创建逻辑,客户端不需要知道如何创建具体的产品对象,只需要关心最终能得到哪些产品。这种模式通常用于解决产品集的变化而无需修改客户端代码的情况。

当需要面对多个产品等级结构时,更推荐使用抽象工厂模式。

抽象工厂模式在现实生活中的抽象实例:

汽车制造:对于每个品牌的汽车,公司都有不同的组件供应商,例如发动机、座椅和轮胎供应商。在抽象工厂模式中,汽车制造公司充当工厂角色,而不同品牌的汽车和不同的组件供应商充当具体产品。

美食餐厅:餐厅可以提供多种类型的饮料和食物,比如咖啡和披萨。每种类型的饮料和食物都有不同的原料供应商。在抽象工厂模式中,餐厅充当工厂角色,而不同类型的饮料和食物以及不同的原料供应商充当具体产品。

电子产品制造:假设有一家电子产品制造公司,对于每种电子产品,公司都有不同的组件供应商,例如显示屏、处理器和电池供应商。在抽象工厂模式中,电子产品制造公司充当工厂角色,而不同类型的电子产品和不同的组件供应商充当具体产品。

二、抽象工厂模式的结构

抽象工厂模式主要包含以下组件:

1.抽象工厂(AbstractFactory):它声明了创建一系列具有相同接口的对象的方法,这些对象代表不同的产品。

2.具体工厂(ConcreteFactory):是抽象工厂的具体实现,负责创建具体产品对象。每个具体工厂对应了一系列的具体产品。

3.抽象产品(AbstractProduct):它声明了产品对象的接口,包含了创建产品的公共方法。

4.具体产品(ConcreteProduct):是抽象产品的具体实现。

组件之间的工作步骤如下:

1.定义一个抽象工厂类, 这个类声明了一系列产品的创建方法,但不提供方法的具体代码实现。

2.代码在特定的上下文环境中调用具体工厂对象来负责创建一系列的产品。

3. 当客户端需要一个产品时,它向抽象工厂发送请求。抽象工厂根据当前需求选择合适的具体工厂,并由该工厂返回所需的产品实例。

抽象工厂模式将具体产品的创建和使用进行了解耦,使得客户端与具体产品的实现分离,能够很方便地替换不同的产品系列。

对应UML类图:

三、抽象工厂模式代码样例

#include <iostream>
using namespace std;
// Abstract Product A
class AbstractProductA {
public:
    virtual void operationA() = 0;
};
// Concrete Product A1
class ProductA1 : public AbstractProductA {
public:
    void operationA() override {
        cout << "Product A1 operation" << endl;
    }
};
// Concrete Product A2
class ProductA2 : public AbstractProductA {
public:
    void operationA() override {
        cout << "Product A2 operation" << endl;
    }
};
// Abstract Product B
class AbstractProductB {
public:
    virtual void operationB() = 0;
};
// Concrete Product B1
class ProductB1 : public AbstractProductB {
public:
    void operationB() override {
        cout << "Product B1 operation" << endl;
    }
};
// Concrete Product B2
class ProductB2 : public AbstractProductB {
public:
    void operationB() override {
        cout << "Product B2 operation" << endl;
    }
};
// Abstract Factory
class AbstractFactory {
public:
    virtual AbstractProductA* createProductA() = 0;
    virtual AbstractProductB* createProductB() = 0;
};
// Concrete Factory 1
class ConcreteFactory1 : public AbstractFactory {
public:
    AbstractProductA* createProductA() override {
        return new ProductA1();
    }
    AbstractProductB* createProductB() override {
        return new ProductB1();
    }
};
// Concrete Factory 2
class ConcreteFactory2 : public AbstractFactory {
public:
    AbstractProductA* createProductA() override {
        return new ProductA2();
    }
    AbstractProductB* createProductB() override {
        return new ProductB2();
    }
};
int main() {
    AbstractFactory* factory1 = new ConcreteFactory1();
    AbstractProductA* productA1 = factory1->createProductA();
    AbstractProductB* productB1 = factory1->createProductB();
    productA1->operationA();
    productB1->operationB();
    AbstractFactory* factory2 = new ConcreteFactory2();
    AbstractProductA* productA2 = factory2->createProductA();
    AbstractProductB* productB2 = factory2->createProductB();
    productA2->operationA();
    productB2->operationB();
    delete factory1;
    delete factory2;
    delete productA1;
    delete productB1;
    delete productA2;
    delete productB2;
    return 0;
}

运行结果:

Product A1 operation
Product B1 operation
Product A2 operation
Product B2 operation

四、抽象工厂模式的优缺点

抽象工厂模式的优点:

降低了客户端与具体产品的耦合度。

符合单一职责原则,每个具体工厂类只负责创建特定的产品。

隐藏了对象的创建过程,客户端不需要关心具体的对象创建细节,只需要通过工厂接口获取所需对象即可。

抽象工厂模式的缺点:

当产品族中需要增加新的产品时,既需要扩展抽象工厂的接口,又需要新增一个具体工厂类,大大增加了代码的维护成本。

当需要创建的产品种类非常多时,抽象工厂模式的类数量将急剧增加,导致系统难以维护和理解。

五、代码实战

模拟披萨的制作过程:

PizzaFactory:

NewYorkCheesePizza:bake() -> cut() -> box()

NewYorkPepperoniPizza:bake() -> cut() -> box()

ChicagoCheesePizza:bake() -> cut() -> box()

ChicagoPepperoniPizza:bake() -> cut() -> box()

#include <iostream>

class Pizza {
public:
    virtual void bake() = 0;
    virtual void cut() = 0;
    virtual void box() = 0;
};

class NewYorkCheesePizza : public Pizza {
public:
    void bake() override
    {
        std::cout << "Baking New York-style cheese pizza."
                << std::endl;
    }

    void cut() override
    {
        std::cout << "Cutting New York-style cheese pizza."
                << std::endl;
    }

    void box() override
    {
        std::cout << "Boxing New York-style cheese pizza."
                << std::endl;
    }
};

class NewYorkPepperoniPizza : public Pizza {
public:
    void bake() override
    {
        std::cout
            << "Baking New York-style pepperoni pizza."
            << std::endl;
    }

    void cut() override
    {
        std::cout
            << "Cutting New York-style pepperoni pizza."
            << std::endl;
    }

    void box() override
    {
        std::cout
            << "Boxing New York-style pepperoni pizza."
            << std::endl;
    }
};

class ChicagoCheesePizza : public Pizza {
public:
    void bake() override
    {
        std::cout << "Baking Chicago-style cheese pizza."
                << std::endl;
    }

    void cut() override
    {
        std::cout << "Cutting Chicago-style cheese pizza."
                << std::endl;
    }

    void box() override
    {
        std::cout << "Boxing Chicago-style cheese pizza."
                << std::endl;
    }
};

class ChicagoPepperoniPizza : public Pizza {
public:
    void bake() override
    {
        std::cout << "Baking Chicago-style pepperoni pizza."
                << std::endl;
    }

    void cut() override
    {
        std::cout
            << "Cutting Chicago-style pepperoni pizza."
            << std::endl;
    }

    void box() override
    {
        std::cout << "Boxing Chicago-style pepperoni pizza."
                << std::endl;
    }
};

class PizzaFactory {
public:
    virtual Pizza* createCheesePizza() = 0;
    virtual Pizza* createPepperoniPizza() = 0;
};

class NewYorkPizzaFactory : public PizzaFactory {
public:
    Pizza* createCheesePizza() override
    {
        return new NewYorkCheesePizza();
    }

    Pizza* createPepperoniPizza() override
    {
        return new NewYorkPepperoniPizza();
    }
};

class ChicagoPizzaFactory : public PizzaFactory {
public:
    Pizza* createCheesePizza() override
    {
        return new ChicagoCheesePizza();
    }

    Pizza* createPepperoniPizza() override
    {
        return new ChicagoPepperoniPizza();
    }
};

int main()
{
    PizzaFactory* newYorkFactory
        = new NewYorkPizzaFactory();
    Pizza* newYorkCheesePizza
        = newYorkFactory->createCheesePizza();
    Pizza* newYorkPepperoniPizza
        = newYorkFactory->createPepperoniPizza();

    PizzaFactory* chicagoFactory
        = new ChicagoPizzaFactory();
    Pizza* chicagoCheesePizza
        = chicagoFactory->createCheesePizza();
    Pizza* chicagoPepperoniPizza
        = chicagoFactory->createPepperoniPizza();

    newYorkCheesePizza->bake();
    newYorkCheesePizza->cut();
    newYorkCheesePizza->box();

    newYorkPepperoniPizza->bake();
    newYorkPepperoniPizza->cut();
    newYorkPepperoniPizza->box();

    chicagoCheesePizza->bake();
    chicagoCheesePizza->cut();
    chicagoCheesePizza->box();

    chicagoPepperoniPizza->bake();
    chicagoPepperoniPizza->cut();
    chicagoPepperoniPizza->box();

    delete newYorkFactory;
    delete newYorkCheesePizza;
    delete newYorkPepperoniPizza;
    delete chicagoFactory;
    delete chicagoCheesePizza;
    delete chicagoPepperoniPizza;

    return 0;
}

运行结果:

Baking New York-style cheese pizza.
Cutting New York-style cheese pizza.
Boxing New York-style cheese pizza.
Baking New York-style pepperoni pizza.
Cutting New York-style pepperoni pizza.
Boxing New York-style pepperoni pizza.
Baking Chicago-style cheese pizza.
Cutting Chicago-style cheese pizza.
Boxing Chicago-style cheese pizza.
Baking Chicago-style pepperoni pizza.
Cutting Chicago-style pepperoni pizza.
Boxing Chicago-style pepperoni pizza.

六、参考阅读

https://www.fluentcpp.com/2022/04/06/design-patterns-vs-design-principles-abstract-factory/

https://www.geeksforgeeks.org/abstract-factory-pattern-c-design-patterns/

https://sourcemaking.com/design_patterns/abstract_factory/cpp/before-after

https://www.scaler.com/topics/design-patterns/creational-design-pattern/

抽象工厂模式(附C++代码示例) 阅读详情

相关推荐

【C++实战㊵】C++抽象工厂模式:解锁高效对象创建的密钥

本文聚焦 C++ 抽象工厂模式实战,先阐释其定义 —— 提供创建相关或依赖对象的接口,无需指定具体类,介绍产品族创建、跨平台开发等适用场景,解析抽象工厂、具体工厂等组成结构。接着给出产品族 A、B 的实现代码,对比其与工厂方法模式,说明产品族扩展方法。还分享退化场景、与依赖注入结合、线程安全处理等实战技巧,最后通过跨平台 UI 组件库项目,展示模式在多平台组件创建与测试中的应用,助力开发者掌握该模式高效创建对象的能力。

邓邓子的博客 1202

matinal:S4 HANA 详解ACDOCA与BSEG的区别都在这了

当你在Coding Block中添加自定义字段的时候

matinal 當冬夜漸暖 。公众号:matinal 4577

倍福ADS通讯协议深度解析——从握手到数据包的完整旅程

本文以工程师视角,通过Wireshark抓包实战,深度解析了倍福ADS通讯协议的完整工作流程。从TCP三次握手建立连接,到拆解AMS/TCP信封、AMS Header地址与命令解析,再到ADS Data读写请求的载荷构成,完整呈现了一次数据通讯的“旅程”。文章重点剖析了协议包格式,并结合实际案例,提供了基于协议分析的故障排查思路,帮助开发者深入理解并精准调试工业自动化系统通讯。

weixin_29231725的博客 151

杂货店商品数据集挖掘关联规则实验

(2)选择事务集中前100条事务,选择合适的支持度阈值,使用Apriori算法和FP-growth算法挖掘频繁项集(推荐使用mlxtend包的apriori和fpgrowth函数),并对比apriori算法和fpgrowth算法的时间复杂度;(比如用户1000在2015年3月15日对应的事务为{‘sausage’,’whole milk’,’semi-finished bread’,’yogurt’}),然后按照用户ID递增,时间递增的方式对事务进行排序;7. 排版工整自洽,图表标题准确(10分)

m0_62500122的博客 1441

<202505高项>《【VIP合集】 软考高项(第四版)十大知识域、五大过程组、ITTO输入输出工具、项目绩效域》

软考高项(第四版)十大知识域、五大过程组、ITTO输入输出工具、项目绩效域

Else 的博客 1854

yolov7模型部署流程

yolov7部署流程

算法的猫 1396

【学习系列】SAP RAP 17:RAP应用部署集成至Fiori Launchpad 【S4HC Public Edition】

本文详细介绍了在SAP S/4HANA Cloud环境中部署RAP应用集成到Fiori Launchpad的两种方法:使用BAS(SAP Business Application Studio)和VSCode。主要步骤包括:1)在BTP中配置Destination连接ES环境;2)设置信任关系;3)创建BAS开发空间;4)通过Fiori应用生成器部署RAP应用;5)创建IAM App、Business Catalog和Business Role;6)配置Launchpad Space和Pages。文章还提供

DeveloperMrMeng的博客 961

手把手教你学Simulink实例:基于Simulink的超级电容器充放电仿真

超级电容器(Supercapacitor)是一种高容量电容器,具有快速充放电能力、长寿命和高功率密度等优点。它在能量存储系统、电动汽车、不间断电源(UPS)等领域有广泛应用。为了更好地理解和设计超级电容器的应用系统,通常需要进行详细的仿真分析。Simulink 提供了一个强大的仿真环境,可以用来设计、分析和验证超级电容器充放电系统的控制策略。本教程将详细介绍如何使用 Simulink 进行超级电容器充放电的仿真实例。通过本教程,我们详细介绍了如何使用 Simulink 进行超级电容器充放电的仿真实例。

MHD0815的博客 581

【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏1(附项目源码)

当今,塔防游戏已经成为游戏市场上备受欢迎的一类游戏类型。《保卫萝卜》作为其中的经典之作,深受玩家喜爱。本项目旨在基于《保卫萝卜》的玩法和特点,开发一个Unity2D塔防游戏,让玩家可以在游戏中体验到精彩的策略对抗与刺激的关卡挑战。本项目将通过Unity引擎进行开发,利用2D游戏开发相关技术,包括但不限于精灵动画、碰撞检测、UI界面设计等。我们将实现萝卜作为关键角色的防守任务,并设计各种怪物和防御塔,使得游戏具有多样的战术策略和游戏乐趣。

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 4924

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

上一篇: C++设计模式——Factory Method工厂方法模式
下一篇: C++设计模式——Singleton单例模式
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员与背包客_CoderZ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值