C++设计模式|创建型 2.工厂模式

1.简单工厂思想

简单工厂模式不属于23种设计模式之⼀,更多的是⼀种编程习惯。它的核心思想是将产品的创建过程封装在⼀个⼯⼚类中,把创建对象的流程集中在这个⼯⼚类⾥⾯。卡码网将其结构描述为下图所示的情况:

简单⼯⼚模式包括三个主要⻆⾊,⼯⼚类、抽象产品类、具体产品类。它们的职责如下:

  • ⼯⼚类:负责创建产品,根据传递的不同参数创建不同的产品示例。
  • 抽象产品类:由工厂类提供的接口,⽐如上图中的 Shape 接⼝,描述产品的通⽤⾏为。
  • 具体产品类:实现抽象产品接⼝或继承抽象产品类,⽐如上⾯的 Circle 类和 Square 类,具体产品通过简单⼯⼚类的 if-else 逻辑来实例化。

 简单工厂的优点是简化了客户端的操作,客户端可以调用工厂方法来获取具体产品,而无需直接与具体产品类交互,降低了耦合,但是有一个很大的问题就是不够灵活,如果需要添加新的产品,就需要修改工厂类的代码

2.什么是工厂模式?

简单工厂的思想中只有一个工厂类,用于创建所有的产品,如果需要添加新的产品,就需要修改工厂类的代码。而工厂模式引入了抽象工厂和具体工厂的概念,每个具体工厂只负责创建一个具体产品,添加新产品时只需要添加新的工厂类,支持扩展,复合开闭原则。

工厂方法模式分为以下几个角色:

  • 抽象工厂:一个接口,包含一个抽象的工厂方法,该方法用于创建产品对象
  • 具体工厂:实现抽象工厂接口,创建具体的产品。
  • 抽象产品类:定义产品的接口。
  • 具体产品类:实现抽象产品接口,是工厂创建的对象。

 工厂模式的示意图如下图所示,实际的生产系统所管理的是对应的工厂,工厂负责产品的生产。当有具体需求传入时,生产提供根据需求创建对应的工厂,这些工厂去完成需求产品的生产。在有新的产品时,只需要扩展一下产品的内容及其对应的工厂即可,原来的代码无需更改,只需要往里面添加新的模块即可,非常灵活。

 3.C++工厂模式

【设计模式专题之工厂方法模式】2.积木工厂 (kamacoder.com)icon-default.png?t=N7T8https://kamacoder.com/problempage.php?pid=1076

题目描述:

小明家有两个工厂,一个用于生产圆形积木,一个用于生产方形积木,请你帮他设计一个积木工厂系统,记录积木生产的信息。

输入描述

输入的第一行是一个整数 N(1 ≤ N ≤ 100),表示生产的次数。 

接下来的 N 行,每行输入一个字符串和一个整数,字符串表示积木的类型。积木类型分为 "Circle" 和 "Square" 两种。整数表示该积木生产的数量

输出描述

对于每个积木,输出一行字符串表示该积木的信息。

输入示例

3
Circle 1
Square 2
Circle 1

 输出示例

Circle Block
Square Block
Square Block
Circle Block

代码实现: 

先实现抽象产品类和具体产品类:

//抽象积木产品类,定义生产具体积木的接口produce()
class Block{
public://写成纯虚函数,一方面将该类变成抽象类,另一方面方便具体产品类实现多态virtual void produce() = 0;
};//具体圆形积木产品类
class CircleBlock: public Block{
public://重写父类虚函数,使用override关键字编译器会检查重写是否正确,不是非要加void produce() override {cout<<"Circle Block"<<endl;}
};//具体方形积木产品类
class SquareBlock: public Block{
public://重写父类虚函数void produce() override{cout<<"Square Block"<<endl;}
};

再实现抽象工厂类和具体工厂类,其中具体工厂类要调用具体产品的生产函数,所以工厂类写在了产品类的后面:

//抽象工厂类,提供一个抽象的接口用于创建对象。具体哪种对象还得用多态实现
class BlockFactory{
public://抽象的接口。 使用积木的基类指针作为返回值,其可以接收圆形或方形的积木对象(C++多态允许)virtual Block* createBlock() = 0;
};//具体圆形积木工厂类
class CircleBlockFactory:public BlockFactory{
public:  //重写接口函数Block* createBlock() override{return new CircleBlock();  //堆区开辟内存存放积木对象}
};//具体方形积木工厂类
class SquareBlockFactory:public BlockFactory{
public:  //重写接口函数Block* createBlock() override{return new SquareBlock();  //堆区开辟内存存放积木对象}
};

建立积木工厂系统。该系统根据输入要求去建立相对应的工厂,让该工厂去生产具体产品:

//建立积木工厂系统
class BlockManageSystem{
private://使用Block*动态数组来记录积木信息vector<Block *> blocks;
public://根据输入,建立积木生产函数。根据具体产品类型调用相对应的产品工厂void produceBlocks(BlockFactory* factory, int num){for(int i=0; i<num; i++){Block* block = factory->createBlock();this->blocks.push_back(block);block->produce();}}//由于具体积木存放在堆区,所以要使用delete进行内存释放~BlockManageSystem(){for(Block* block : blocks){delete block;}}//获取所有积木。第一个const修饰返回的引用,即使得到积木,也不能对积木进行修改。//第二个const修饰this指针,保证this指针不能对积木进行修改const vector<Block*> & getBlocks()const{return blocks;}};

总体代码:

#include<iostream>
#include<vector>
#include<string>
using namespace std;//按照工厂模式的组成,依次实现抽象产品类、具体产品类、抽象工厂类、具体工厂类//抽象积木产品类,定义生产具体积木的接口produce()
class Block{
public://写成纯虚函数,一方面将该类变成抽象类,另一方面方便具体产品类实现多态virtual void produce() = 0;
};//具体圆形积木产品类
class CircleBlock: public Block{
public://重写父类虚函数void produce() override {cout<<"Circle Block"<<endl;}
};//具体方形积木产品类
class SquareBlock: public Block{
public://重写父类虚函数,使用override关键字编译器会检查重写是否正确,不是非要加void produce() override{cout<<"Square Block"<<endl;}
};//抽象工厂类,提供一个抽象的接口用于创建对象。具体哪种对象还得用多态实现
class BlockFactory{
public://抽象的接口。 使用积木的基类指针作为返回值,其可以接收圆形或方形的积木对象(C++多态允许)virtual Block* createBlock() = 0;
};//具体圆形积木工厂类
class CircleBlockFactory:public BlockFactory{
public:  //重写接口函数Block* createBlock() override{return new CircleBlock();  //堆区开辟内存存放积木对象}
};//具体方形积木工厂类
class SquareBlockFactory:public BlockFactory{
public:  //重写接口函数Block* createBlock() override{return new SquareBlock();  //堆区开辟内存存放积木对象}
};//建立积木工厂系统
class BlockManageSystem{
private://使用Block*动态数组来记录积木信息vector<Block *> blocks;
public://根据输入,建立积木生产函数。根据具体产品类型调用相对应的产品工厂void produceBlocks(BlockFactory* factory, int num){for(int i=0; i<num; i++){Block* block = factory->createBlock();this->blocks.push_back(block);block->produce();}}//由于具体积木存放在堆区,所以要使用delete进行内存释放~BlockManageSystem(){for(Block* block : blocks){delete block;}}//获取所有积木。第一个const修饰返回的引用,即使得到积木,也不能对积木进行修改。//第二个const修饰this指针,保证this指针不能对积木进行修改const vector<Block*> & getBlocks()const{return blocks;}};int main()
{int produceNum;  //生产次数cin>>produceNum;BlockManageSystem mySystem;  //创建积木工厂系统for(int i=0; i< produceNum; i++){string blockType;int blockNum;//读取生产积木的类型和数量cin>>blockType>>blockNum;if(blockType == "Circle") {//需要使用工厂系统调用圆形积木工厂启动生产mySystem.produceBlocks(new CircleBlockFactory(),blockNum);}else if (blockType == "Square") {//需要使用工厂系统调用方形积木工厂启动生产mySystem.produceBlocks(new SquareBlockFactory(),blockNum);}}return 0;
}

4.工厂模式应用场景

工厂方法模式使得每个工厂类的职责单一每个工厂只负责创建一种产品,当创建对象涉及一系列复杂的初始化逻辑,而这些逻辑在不同的子类中可能有所不同时,可以使用工厂方法模式将这些初始化逻辑封装在子类的工厂中。

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

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

相关文章

apache配置ssl证书

SSL证书&#xff0c;即安全套接层证书&#xff0c;是一种数字证书&#xff0c;它通过在客户端浏览器和Web服务器之间建立一条加密通道&#xff0c;保证了双方传输信息的安全性。当用户访问一个使用SSL证书保护的网站时&#xff0c;浏览器会显示一个锁形图标&#xff0c;表示连接…

OWASP发布10大开源软件风险清单

3月20日&#xff0c;xz-utils 项目被爆植入后门震惊了整个开源社区&#xff0c;2021 年 Apache Log4j 漏洞事件依旧历历在目。倘若该后门未被及时发现&#xff0c;那么将很有可能成为影响最大的软件供应链漏洞之一。近几年爆发的一系列供应链漏洞和风险&#xff0c;使得“加强开…

【Java集合进阶】数据结构(平衡二又树旋转机制)数据结构(红黑树、红黑规则、添加节点处理方案详解)

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏 …

鸿蒙入门02-首次安装和配置

注&#xff1a;还没有安装编辑器&#xff08; deveco studio &#xff09;的小伙伴请看鸿蒙入门01-下载和安装-CSDN博客 首次安装配置 编辑器&#xff08; deveco studio &#xff09;安装完毕以后需要进入配置界面进行相关配置配置完毕以后才可以正常使用 环境配置&#xf…

算法打卡day36

今日任务&#xff1a; 1&#xff09;01背包问题理论基础(卡码网&#xff1a;46. 携带研究材料) 2&#xff09;01背包问题滚动数组(卡码网&#xff1a;46. 携带研究材料) 3&#xff09;416. 分割等和子集 4&#xff09;复习day11 卡码网&#xff1a;46. 携带研究材料 题目链接&…

RUST腐蚀服务器添加 TAGS标签教程

RUST腐蚀服务器添加 TAGS标签教程 大家好我是艾西&#xff0c;一个做服务器租用的网络架构师。我们自己搭建架设的服务器在steam展示面板看到跟别人的不一样是咋回事&#xff1f; 这个其实就是服务器的一个标签&#xff0c;那么主要的作用就是让大家在选择服务器时更快更直接的…

SpringBoot项目基于java的教学辅助平台

采用技术 SpringBoot项目基于java的教学辅助平台的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBootMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 页面展示效果 学生信息管理 教师信息管理 课程信息管理 科目分类管…

vagrant 安装虚拟机,docker, k8s

第一步&#xff1a;安装虚拟机 1、安装 vagrant 本机是 mac, 但是这一步不影响&#xff0c;找对应操作系统的安装方式就行了。 vagrant 下载地址 brew install vagrant 2、下载 VirtualBox 虚拟机 VirtualBox 下载地址 找到对应系统下载&#xff0c;安装就可以。 尽量把…

【位运算 子集状态压缩】982按位与为零的三元组

算法可以发掘本质&#xff0c;如&#xff1a; 一&#xff0c;若干师傅和徒弟互有好感&#xff0c;有好感的师徒可以结对学习。师傅和徒弟都只能参加一个对子。如何让对子最多。 二&#xff0c;有无限多1X2和2X1的骨牌&#xff0c;某个棋盘若干格子坏了&#xff0c;如何在没有坏…

淘系电商课程,0基础实战教学,实操性系统性实时性

课程下载&#xff1a;https://download.csdn.net/download/m0_66047725/89064789 更多资源下载&#xff1a;关注我。 课程内容&#xff1a; 00.前言一做好电商的基本认知 .mp4 01.电商卖货的底层逻辑和权重解析,mp4 02.做好产品的前期准备工作.mp4 03.店铺如何布局产品,m…

Java复习第二十天学习笔记(过滤器Filter),附有道云笔记链接

【有道云笔记】二十 4.8 过滤器Filter https://note.youdao.com/s/dSofip3f 一、为什么要使用过滤器 项目开发中&#xff0c;经常会用到重复代码的实现。 1、请求每个servlet都要设置编码 2、判断用户是否登录&#xff0c;只有登录了才有操作权限。 二、过滤器相关Api int…

Linux内核之WRITE_ONCE用法实例(四十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…