C++设计模式|创建型 3.抽象工厂模式

在上一篇文章中介绍了工厂模式,每个具体工厂负责生产一个专门的产品,其代码扩展性很好,这篇文章将介绍抽象工厂模式。

1.为什么要使用抽象工厂模式?

既然已经有了“工厂模式”,那为什么还会有抽象工厂模式呢?

这就涉及到创建“多类”对象了,在工厂方法模式中,每个具体工厂只负责创建单一的产品。但是如果有多类产品呢,比如说“手机”,一个品牌的手机有高端机、中低端机之分,这些具体的产品在工厂模式中都需要建立一个单独的工厂类,但是它们都是相互关联的,都共同属于同一个品牌,这就可以使用到【抽象工厂模式】。

抽象工厂模式可以确保一系列相关的产品被一起创建,这些产品能够相互配合使用,再举个例子,有一些家具,比如沙发、茶几、椅子,都具有古典风格的和现代风格的,抽象工厂模式可以将生产现代风格的家具放在一个工厂类中,将生产古典风格的家具放在另一个工厂类中,这样每个工厂类就可以生产一系列的家具

2.抽象工厂模式的基本结构

抽象工厂模式包含多个抽象产品类,多个具体产品类,一个抽象工厂接口和多个具体工厂类,给个具体工厂杜泽创建一组相关的产品。

  • 抽象产品接口AbstractProduct: 定义产品的接口,可以定义多个抽象产品接口,比如说沙发、椅子、茶几都是抽象产品。所谓抽象产品接口,其实就是表示生产产品的一个纯虚函数,具体实现由下面的具体产品类实现。
  • 具体产品类ConcreteProduct: 实现抽象产品接口,产品的具体实现,古典风格和沙发和现代风格的沙发都是具体产品。
  • 抽象工厂接口AbstractFactory: 声明一组用于创建产品的方法,每个方法对应一类产品。该接口也是纯虚函数,具体实现有具体工厂类完成。
  • 具体工厂类ConcreteFactory 实现抽象工厂接口,负责创建一组具体产品的对象,在本例中,生产古典风格的工厂和生产现代风格的工厂都是具体实例。

 下面可以根据具体代码再理解上面的内容。

3.C++抽象工厂模式

【设计模式专题之抽象工厂模式】3. 家具工厂 (kamacoder.com)icon-default.png?t=N7T8https://kamacoder.com/problempage.php?pid=1077

题目描述:

小明家新开了两个工厂用来生产家具,一个生产现代风格的沙发和椅子,一个生产古典风格的沙发和椅子,现在工厂收到了一笔订单,请你帮他设计一个系统,描述订单需要生产家具的信息。

输入描述:

输入的第一行是一个整数 N(1 ≤ N ≤ 100),表示订单的数量。 

接下来的 N 行,每行输入一个字符串,字符串表示家具的类型。家具类型分为 "modern" 和 "classical" 两种。

输出描述:

对于每笔订单,输出字符串表示该订单需要生产家具的信息。 

modern订单会输出下面两行字符串 

modern chair 

modern sofa

classical订单会输出下面两行字符串 

classical chair 

classical sofa

输入示例: 

3
modern
classical
modern

输出示例:

modern chair
modern sofa
classical chair
classical sofa
modern chair
modern sofa

在上面的示例中,工厂收到了3笔订单,其中有2笔要求生产modern风格,1笔要求生产classical风格。根据输入的类型,每次订单生产的家具信息被输出到控制台上。 

代码实现: 

1.多个抽象产品类和多个具体产品类

根据题目,生产的产品有椅子和沙发两种,每种产品有现代和古典两种风格,那个椅子和沙发会各自对应一个抽象产品类,而现代椅子和古典椅子,现代沙发和古典沙发将是这两个抽象产品类的具体产品类。代码如下:

//抽象椅子类,里面包含生产接口produce()
class Chair{
public://抽象产品生产接口virtual void produce() = 0;
};//具体现代风格椅子类
class ModernChair : public Chair{
public://多态实现具体抽象产品生产接口的具体化void produce() override{cout<<"modern chair"<<endl;}
};//具体古典风格椅子类
class ClassicalChair : public Chair{
public:
//多态实现具体抽象产品生产接口的具体化void produce() override{cout<<"classical chair"<<endl;}
};//抽象沙发类
class Sofa{
public:virtual void produce() = 0;
};//具体现代沙发类
class ModernSofa:public Sofa{
public:void produce() override{cout<<"modern sofa"<<endl;}
};//具体古典沙发类
class ClassicalSofa:public Sofa{
public:void produce() override{cout<<"classical sofa"<<endl;}
};

 2.一个抽象工厂类和多个具体工厂类

抽象工厂定义了生产产品的动作接口,具体工厂可以生产同风格的多种产品。

/下面是抽象工厂类,声明一组用于创建产品的方法,每个方法对应一种产品
class AbstractFurnitureFactory{
public:virtual Chair* createChair() = 0;virtual Sofa* createSofa() = 0;
};//有了抽象工厂,需要设计具体工厂类,每个类负责生产同一风格的多种不同产品//具体现代风格家具工厂类
class ModernFurnitureFactory:public AbstractFurnitureFactory{
public://生产现代风格的椅子Chair * createChair() override{return new ModernChair();}//生产现代风格的沙发Sofa* createSofa() override{return new ModernSofa();}};//具体古典风格家具工厂类
class ClassicalFurnitureFactory:public AbstractFurnitureFactory{
public://生产古典风格的椅子Chair * createChair() override{return new ClassicalChair();}//生产古典风格的沙发Sofa* createSofa() override{return new ClassicalSofa();}};

整体代码如下:

#include<iostream>
#include<string>
using namespace std;//生产的产品大类有椅子chair和沙发sofa两种
//根据抽象工厂模式的要求,要有抽象产品类及其对应的具体产品类
//所以下面先创建chair和sofa的抽象产品类//抽象椅子类,里面包含生产接口produce()
class Chair{
public:virtual void produce() = 0;
};//具体现代风格椅子类
class ModernChair : public Chair{
public:void produce() override{cout<<"modern chair"<<endl;}
};//具体古典风格椅子类
class ClassicalChair : public Chair{
public:void produce() override{cout<<"classical chair"<<endl;}
};//抽象沙发类
class Sofa{
public:virtual void produce() = 0;
};//具体现代沙发类
class ModernSofa:public Sofa{
public:void produce() override{cout<<"modern sofa"<<endl;}
};//具体古典沙发类
class ClassicalSofa:public Sofa{
public:void produce() override{cout<<"classical sofa"<<endl;}
};//下面是抽象工厂类,声明一组用于创建产品的方法,每个方法对应一种产品
class AbstractFurnitureFactory{
public:virtual Chair* createChair() = 0;virtual Sofa* createSofa() = 0;
};//有了抽象工厂,需要设计具体工厂类,每个类负责生产同一风格的多种不同产品//具体现代风格家具工厂类
class ModernFurnitureFactory:public AbstractFurnitureFactory{
public://生产现代风格的椅子Chair * createChair() override{return new ModernChair();}//生产现代风格的沙发Sofa* createSofa() override{return new ModernSofa();}};//具体古典风格家具工厂类
class ClassicalFurnitureFactory:public AbstractFurnitureFactory{
public://生产古典风格的椅子Chair * createChair() override{return new ClassicalChair();}//生产古典风格的沙发Sofa* createSofa() override{return new ClassicalSofa();}};int main()
{//读取订单数量int N;cin>>N;//处理订单for(int i=0; i<N; ++i){string furnitureType; //准备读取家具类型cin>>furnitureType;//创建相应风格的具体家具工厂AbstractFurnitureFactory * factory = nullptr;if(furnitureType == "modern"){factory = new ModernFurnitureFactory();}else if(furnitureType == "classical"){factory = new ClassicalFurnitureFactory();    }//工厂去生产同风格的多个产品//生产该风格的椅子Chair * chair = factory->createChair();//生产该风格的沙发Sofa * sofa = factory->createSofa();//输出信息chair->produce();sofa->produce();//内存释放delete chair;delete sofa;delete factory;}return 0;
}

简单工厂、工厂模式、抽象工厂模式的区别

  • 简单工厂模式:一个工厂方法创建所有具体产品

  • 工厂方法模式:一个具体工厂方法创建一个具体产品

  • 抽象工厂模式:一个具体工厂方法可以创建一类具体产品

抽象工厂模式应用场景: 

抽象工厂模式能够保证一系列相关的产品一起使用,并且在不修改客户端代码的情况下,可以方便地替换整个产品系列。但是当需要增加新的产品类时,除了要增加新的具体产品类,还需要添加新的抽象工厂接口,修改所有的具体工厂类的生产函数(使其也能够同时生产该类型的新产品),扩展性相对较差。因此抽象工厂模式特别适用于一系列相关或相互依赖的产品被一起创建的情况,典型的应用场景是使用抽象工厂模式来创建与不同数据库的连接对象。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/824164.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu常用方法

文本文件的创建&#xff1a; sudo touch ubuntu.txt move clock: sudo chmod 777 ubuntu.txt 安装chrome wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb sudo apt install ./google-chrome-stable_current_amd64.deb .sh 文件的安装 例…

生成人工智能体:人类行为的交互式模拟论文与源码架构解析(1)——场景故事介绍

生成NPC为交互应用程序创建逼真的人类行为模拟。在这项工作中&#xff0c;我们通过将二十五个NPC放置在一个沙盒环境中&#xff08;类似于The Sims&#xff0c;模拟人生&#xff09;&#xff0c;展示了生成NPC的能力。用户可以观察和干预NPC的日常计划、分享新闻、建立关系以及…

web配置https

Tomcat8 配置&#xff1a; 1.单向认证&#xff0c;就是传输的数据加密过了&#xff0c;但是不会校验客户端的来源 2.双向认证&#xff0c;如果客户端浏览器没有导入客户端证书&#xff0c;是访问不了web系统的&#xff0c;找不到地址 如果只是加密&#xff0c;我感觉单向就行…

就业班 第三阶段(ansible) 2401--4.16 day2 ansible2 剧本+角色

六、Ansible playbook 简介 playbook 是 ansible 用于配置&#xff0c;部署&#xff0c;和管理被控节点的剧本。   通过 playbook 的详细描述&#xff0c;执行其中的一系列 tasks &#xff0c;可以让远端主机达到预期的状态。playbook 就像 Ansible 控制器给被控节点列出的的…

人工智能电话机器人常见的问题有哪些?

随着业务的不断拓展&#xff0c;电销业务量也不断攀升。公司为了控制用人成本&#xff0c;电销人员数量有限&#xff0c;而且培训上岗周期慢&#xff0c;这就导致成交率、销售额无法完成&#xff0c;电话机器人的出现&#xff0c;有效的解决了这些痛点&#xff0c;只需电销人员…

广东海洋大学成功部署(泰迪智能科技)大数据人工智能实验室建设

广东海洋大学简称广东海大&#xff0c;坐落于广东省湛江市&#xff0c;是国家海洋局与广东省人民政府共建的省属重点建设大学、广东省高水平大学重点学科建设高校、粤港澳高校联盟成员 &#xff0c;入选卓越农林人才教育培养计划&#xff0c;是教育部本科教学水平评估优秀院校。…

odoo添加自定义网页---添加模块图标

1.新建一个模块 python odoo-bin scaffold test_web <路径> 2.我们需要修改一下几个文件 3.web.xml <?xml version"1.0" encoding"UTF-8"?> <templates id"template" xml:space"preserve"><t t-name"T…

uniapp封装websocket以及心跳检测、重连

websocket 封装 在所需文件夹下建立websocketUtils.js文件&#xff0c;封装代码如下&#xff1a; class websocketUtils {constructor(openId, time) {this.url wss://**** //ws地址 拼接一下 此处用的是openIdthis.data nullthis.isOpenSocket false //避免重复连接this.…

详解汽车交流充电桩主板的四大版本

近年来&#xff0c;在电动汽车行业快速发展背景下&#xff0c;充电桩的建设变得愈发重要&#xff0c;特别是兼容性较高、适用性较广的交流充电桩。 交流充电桩的心脏——主板的设计与功能&#xff0c;对于充电桩的性能和用户体验起着至关重要的作用。目前&#xff0c;市面上的…

OpenCV 常见数据类型

OpenCV 是一个轻量级高效的跨平台计算机视觉库&#xff0c;实现了图像处理和计算机视觉方面的多种通用算法。所谓的图像可以理解为一个数组&#xff0c;图像处理就是对数组的处理。首先&#xff0c;本文将介绍 OpenCV 中常见的数据类型&#xff0c;包括点 Point类、颜色 Scalar…

康谋技术 | 深入探讨:自动驾驶中的相机标定技术

随着自动驾驶技术的快速发展&#xff0c;多传感器的数据采集和融合可以显著提高系统的冗余度和容错性&#xff0c;进而保证决策的快速性和正确性。在项目开发迭代过程中&#xff0c;传感器标定扮演着至关重要的角色&#xff0c;它位于数据采集平台与感知融合算法之间&#xff0…

今天碰到的一点小问题(网上搜了一下理解了一下

在编程中&#xff0c;let 是一个关键字&#xff0c;主要用于声明一个块级作用域的局部变量。它是在 ECMAScript 2015&#xff08;也称为 ES6&#xff09;中引入的&#xff0c;以替代 var 关键字&#xff0c;用于解决 var 的一些作用域问题。 使用 let 声明的变量具有以下特点&…

如何使用自定义Promptbooks优化您的安全工作流程

在当今的数字化时代&#xff0c;安全工作流程的优化变得前所未有的重要。安全团队需要快速、有效地响应安全事件&#xff0c;以保护组织的数据和资产。Microsoft Copilot for Security提供了一种强大的工具——自定义Promptbooks&#xff0c;它可以帮助安全专家通过自动化和定制…

Swift高级特性之泛型

泛型是一种在编程语言中实现通用性的特性&#xff0c;它允许我们编写可以适应不同数据类型的代码。在Swift中&#xff0c;泛型可以应用于函数、类、结构体和枚举。 1.泛型函数&#xff1a;使用泛型函数可以编写一次代码&#xff0c;用于处理不同类型的数据。例如&#xff0c;我…

Linux下git维护

目录 1、安装 2、git是一个版本控制器 3、git操作 1、 #将文件放到本地仓库 2、#提交到本地 3、#远端修改同步&#xff08;需输密码&#xff09; 4、#查看提交日志 5、#删除对应文件 4、相关理解&#xff1a; 1、安装 sudo yum -y install git 2、git是一个版本控制器…

tmux 命令速查 导图

最近在使用tmux&#xff0c;整理了一份命令的导图&#xff0c;大家需要自取&#xff5e; tmux是什么&#xff1f; Tmux是一个终端复用器&#xff0c;一个非常有用的linux开发工具。 基本概念 会话&#xff1a; 与命令下的终端窗口类似&#xff1b;tmux进程&#xff0c;可包…

SpringBoot整合Swagger2

SpringBoot整合Swagger2 1.什么是Swagger2&#xff1f;&#xff08;应用场景&#xff09;2.项目中如何使用2.1 导入依赖2.2 编写配置类2.3 注解使用2.3.1 controller注解&#xff1a;2.3.2 方法注解2.3.3 实体类注解2.3.4 方法返回值注解2.3.5 忽略的方法 3.UI界面 1.什么是Swa…

浅谈PyExecJS模块

浅谈PyExecJS模块 PyExecJS 是一个 Python 模块&#xff0c;用于在 Python 中执行 JavaScript 代码。 PyExecJS 模块的主要作用&#xff1a; 执行 JavaScript 代码&#xff1a;允许在 Python 环境中执行 JavaScript 代码&#xff0c;这在一些需要跨语言处理或评估 JavaScript…

短视频矩阵系统----技术源头开发

短视频矩阵系统--- 1. 确定账号类型和目标受众 2. 准备账号资料 3. 搭建系统框架 4. 开发核心功能 5. 测试和调试 6. 部署和维护 7. 推广和运营 在开发短视频账号矩阵系统源码时&#xff0c;可以使用一些开源框架和工具来提高开发效率和降低开发难度。同时&#xff0c;需要组…

Qt查询mysql表的信息解释

Qt如何查询表中的数据呢&#xff1f; 首先我们需要连接数据库&#xff0c;连接完了&#xff0c;我们进行操作数据库。 连接数据库的代码&#xff1a; bool MainWindow::connectToDatabase(QSqlDatabase &db, const QString &host, const QString &dbName, const…