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

别再纠结了!实测罗技Flow、对拷线、微软Mouse without Borders,我的最终选择是...

本文通过实测对比罗技Flow、对拷线和微软Mouse without Borders等多设备控制方案,详细分析了各自的优缺点及适用场景。作者最终选择了对拷线与罗技键鼠的组合方案,为专业用户提供了稳定可靠的多设备协同办公解决方案,特别适合需要频繁传输大文件和跨设备操作的用户。

weixin_33696106的博客 405

matlab电容式传感器仿真,差动电容式位移传感器的仿真研究

设计了一种差动电容式位移传感器,主要对传感器的数学模型及电容检测电路进行了仿真研究。其中检测电路设计主要包括正弦激励电路、转换桥路、信号放大电路、精密整流电路和滤波电路。最后利用Matlab/SimurFnk软件对所设计的系统进行仿真,并分析了传感器性能。仿真研究表明,传感器及其检测电路具有合理性,测量范围内具有很好的线性度。0|| I≯ lat on ii{差动容尊翩’亘研发注:湖南省教育厅资...

weixin_36323601的博客 1390

Android Studio运行报错: failed to load include path ……\platforms\android-35\android.jar的最细解决方案

【代码】Android Studio运行报错: failed to load include path ……\platforms\android-35\android.jar的最细解决方案。

2401_86789230的博客 2万+

APB Timer验证环境搭建——学习笔记(1)

以下为个人学习笔记,如有疏漏,请大家指正补充~~APB Timer是一个简单的下行计数器,包括一个32位计数器和一组比较器,可以实现多种计时功能。包括生成一次性中断或者定时中断。

qq_41651535的博客 1578

leetcode134 加油站

题目如下 在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。 你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。 如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。 说明: 如果题目有解,该答案即为唯一答案。 输入数组均为非空数组,且长度相同。 输...

ayang818 's blog 233

乐企增值税及附加税费预缴申报表填报能力说明文档V1.004

申报表填报,是指企业在自有业务系统中将算税结果数据按预填规则要求加工汇总后,进行申报表填报的过程。申报表填报前对纳税申报所需的前提条件进行校验。校验通过后,应用前序算税结果数据及预填规则进行纳税申报表预填,生成申报表数据。申报表数据通过申报业务规则校验后,经纳税人确认即完成申报表填报业务。

记录点滴 355

【系统架构设计师】2026年上半年真题论文:论高并发系统的设计与实践

本文围绕高并发系统架构设计展开,重点论述了电商秒杀系统的实战经验。文章采用"痛点-解决方案-效果"的逻辑结构,从缓存设计、异步处理、限流降级、数据库优化等6个维度详细阐述了应对高并发的技术策略。其中,重点介绍了多级缓存体系、基于消息队列的异步处理机制和微服务拆分实践,并辅以实际案例说明如何解决超卖、缓存雪崩等典型问题。全文强调高并发设计需要系统性思维,通过空间换时间、异步换吞吐、横向换能力等原则,最终实现系统吞吐量从500TPS提升至20000TPS的性能突破。

数据知道的博客 1157

图神经网络实战(2)——图论基础

图论 (Graph theory) 是数学的一个基本分支,涉及对图研究。图是复杂数据结构的可视化表示,有助于理解不同实体之间的关系。图论提供了大量建模和分析现实问题的工具,如交通系统、社交网络和互联网等。在本节中,将介绍图论的基本原理,主要涉及三个方面:图属性、图概念和图算法。

盼小辉丶的博客 1万+

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

VC中sqlite的使用

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

上一篇: 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、付费专栏及课程。

余额充值