创建型模式--3.工厂模式 【人造恶魔果实工厂2】

1. 简单工厂模式的弊端

在上一节简单工厂模式中,创建了一个工厂类,用于生产需要的对象,但是这种方式有一个弊端,它违反了设计模式中的开放-封闭原则,先来看相关的代码:

// 恶魔果实工厂类
enum class Type:char{SHEEP, LION, BAT};
class SmileFactory
{
public:SmileFactory() {}~SmileFactory() {}AbstractSmile* createSmile(Type type){AbstractSmile* ptr = nullptr;switch (type){case Type::SHEEP:ptr = new SheepSmile;break;case Type::LION:ptr = new LionSmile;break;case Type::BAT:ptr = new BatSmile;break;default:break;}return ptr;}
};

在上面的工厂函数中需要生成三种人造恶魔果实,现在如果想要生成更多,那么就需要在工厂函数的switch语句中添加更多的case,很明显这违背了封闭原则,也就意味着需要基于开放原则来解决这个问题。

使用工厂模式可以很完美的解决上述的问题,简单工厂模式是只有一个工厂类,而工厂模式是有很多的工厂类:

  • 一个基类,包含一个虚工厂函数,用于实现多态。
  • 多个子类,重写父类的工厂函数。每个子工厂类负责生产一种恶魔果实,这相当于再次解耦,将工厂类的职责再次拆分、细化,如果要生产新品种的恶魔果实,那么只需要添加对应的工厂类,无需修改原有的代码。

2. 工厂模式

我们先修改一下简单工厂模式中工厂类相关的代码:

// 恶魔果实工厂类
class AbstractFactory
{
public:virtual AbstractSmile* createSmile() = 0;virtual ~AbstractFactory() {}
};class SheepFactory : public AbstractFactory
{
public:AbstractSmile* createSmile() override{return new SheepSmile;}~SheepFactory(){cout << "释放 SheepFactory 类相关的内存资源" << endl;}
};class LionFactory : public AbstractFactory
{
public:AbstractSmile* createSmile() override{return new LionSmile;}~LionFactory(){cout << "释放 LionFactory 类相关的内存资源" << endl;}};class BatFactory : public AbstractFactory
{
public:AbstractSmile* createSmile() override{return new BatSmile;}~BatFactory(){cout << "释放 BatFactory 类相关的内存资源" << endl;}
};

通过示例代码可以看到,每个工厂类其实都不复杂,在每个子工厂类中也只是重写了父类的工厂方法而已,每个子工厂类生产一种恶魔果实,但是工厂函数的返回值确是恶魔果实类的基类类型,相当于是使用父类指针指向了子类对象,此处也是用到了多态。通过这样的处理,工厂函数也就不再需要参数了。

根据简单工厂模式的代码和上面的修改就可以把工厂模式的UML类图画出来了:

在这里插入图片描述

完整的代码应该是这样的:

#include <iostream>
using namespace std;class AbstractSmile
{
public:virtual void transform() = 0;virtual void ability() = 0;virtual ~AbstractSmile() {}
};
// 人造恶魔果实· 绵羊形态
class SheepSmile : public AbstractSmile
{
public:void transform() override{cout << "变成人兽 -- 山羊人形态..." << endl;}void ability() override{cout << "将手臂变成绵羊角的招式 -- 巨羊角" << endl;}
};// 人造恶魔果实· 狮子形态
class LionSmile : public AbstractSmile
{
public:void transform() override{cout << "变成人兽 -- 狮子人形态..." << endl;}void ability() override{cout << "火遁· 豪火球之术..." << endl;}
};class BatSmile : public AbstractSmile
{
public:void transform() override{cout << "变成人兽 -- 蝙蝠人形态..." << endl;}void ability() override{cout << "声纳引箭之万剑归宗..." << endl;}
};// 恶魔果实工厂类
class AbstractFactory
{
public:virtual AbstractSmile* createSmile() = 0;virtual ~AbstractFactory() {}
};class SheepFactory : public AbstractFactory
{
public:AbstractSmile* createSmile() override{return new SheepSmile;}~SheepFactory(){cout << "释放 SheepFactory 类相关的内存资源" << endl;}
};class LionFactory : public AbstractFactory
{
public:// 工厂函数AbstractSmile* createSmile() override{return new LionSmile;}~LionFactory(){cout << "释放 LionFactory 类相关的内存资源" << endl;}};class BatFactory : public AbstractFactory
{
public:// 工厂函数AbstractSmile* createSmile() override{return new BatSmile;}~BatFactory(){cout << "释放 BatFactory 类相关的内存资源" << endl;}
};int main()
{AbstractFactory* factory = new BatFactory;AbstractSmile* obj = factory->createSmile();obj->transform();obj->ability();return 0;
}

main()函数中的这句代码是实例化了一个生成蝙蝠恶魔果实的工厂对象:

AbstractFactory* factory = new BatFactory;

在真实的项目场景中,要生成什么类型的恶魔果实其实是通过客户端的操作界面控制的,它对应的可能是一个按钮或者是一个选择列表,用户做出了选择,程序就可以根据该需求去创建对应的工厂对象,最终将选择的恶魔果实生产出来。

在上面的例子中,不论是恶魔果实的基类,还是工厂类的基类,它们的虚函数可以是纯虚函数,也可以是非纯虚函数。这样的基类在设计模式中就可以称之为抽象类(此处的抽象类和C++中对抽象类的定义有一点出入)。

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

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

相关文章

使用美化方法设计项目主窗体(二)

使用美化方法设计项目主窗体 分析效果图的实现 效果图&#xff1a; 新建 Windows 窗体 新窗体命名&#xff1a;FrmMain.cs修改窗体的位置&#xff1a;StartPosition&#xff1a;CenterScreen窗体的无边框设计&#xff1a;FormBorderStyle&#xff1a;none修改窗体的大小&a…

高级优化理论与方法(七)

高级优化理论与方法&#xff08;七&#xff09; Solving Linear EquationsCase 2TheoremKaczmarzs AlgorithmTheoremExample PseudoinverseDefinitionSpecial Case 1Special Case 2 Properties of PseudoinverseLemma 1: Unique pseudoinverseLemma 2: Full Rank Factorization…

MySQL8.3.0 主从复制方案(master/slave)

一 、什么是MySQL主从 MySQL主从&#xff08;Master-Slave&#xff09;复制是一种数据复制机制&#xff0c;用于将一个MySQL数据库服务器&#xff08;主服务器&#xff09;的数据复制到其他一个或多个MySQL数据库服务器&#xff08;从服务器&#xff09;。这种复制机制可以提供…

如何让阿里云AI001号员工帮我写代码(含IDEA插件使用)

国内首个AI程序员入职阿里云&#xff1a;专属工号AI001&#xff0c;KPI是一人写完公司20%代码。 不管是真是假&#xff0c;AI 程序员发展的趋势是无法改变的&#xff0c;小米汽车发布会上&#xff0c;雷军说到小米汽车工厂的自动化率达到90%以上&#xff0c;有些车间甚至100%的…

手术麻醉系统源码 医疗信息管理系统源码C#.net6.0+ vs2022,vscode+BS网页版 手麻系统源码

手术麻醉系统源码 医疗信息管理系统源码C#.net6.0 vs2022,vscodeB/S网页版 手麻系统源码 手术麻醉管理系统是应用于医院手术室、麻醉科室的计算机软件系统。该系统针对整个围术期&#xff0c;对病人进行全程跟踪与信息管理&#xff0c;自动集成病人HIS、LIS、RIS、PACS信息&…

jdk8新特性 方法引用

简介 lambda表达式是用来简化匿名内部类的方法引用 使用来简化 lambda表达式的 方法引用的标志 两个冒号 静态方法 静态方法 class CompareByAge {public static int compare(Student o1, Student o2) {return o1.getAge() - o2.getAge();} }静态方法引用 Arrays.sort(students…

表格比对作业指导书 使用access对excel表格数据进行比对

初级代码游戏的专栏介绍与文章目录-CSDN博客 &#xff08;注&#xff1a;这是以前给秘书写的作业指导书&#xff0c;用来处理两个表格中哪些人存在、哪些人不存在。看起来当时使用的access版本是2016。access是微软office套件中的一个软件&#xff0c;存在于家庭版&#xff0c…

​SCP收容物041~050​

注 &#xff1a;此文接SCP收容物031~040,本文只供开玩笑 ,与steve_gqq_MC合作。 --------------------------------------------------------------------------------------------------------------------------------- 目录 scp-041 scp-042 scp-043 scp-044 scp-045…

二维相位解包理论算法和软件【全文翻译- 噪声滤波(3.53.6)】

3.5 噪音过滤 在本节中,我们将简要讨论相位数据的滤波问题。除了提高信噪比之外,噪声滤波还有助于减少残差的数量,从而大大简化相位解包过程。不过,我们必须注意到一个重要的问题。正如我们在第 1 章中指出的,相位本身并不是信号。它只是信号的一种属性。因此,应该过滤的…

JSON字符串中获取一个特定字段的值

JSON字符串中获取一个特定字段的值 一、方式一&#xff0c;引用gson工具二、方式二&#xff0c;使用jackson三、方式三&#xff0c;使用jackson转换Object四、方式四&#xff0c;使用hutool&#xff0c;获取报文数组数据 一、方式一&#xff0c;引用gson工具 测试报文&#xf…

表单流程管理系统:推进数字化转型理想助手

在数字化转型新时代&#xff0c;谁拥有理想的软件平台助手&#xff0c;谁就能在流程化管理新进程中迈出坚实的步伐。面对激烈的市场竞争&#xff0c;低代码技术平台及表单流程管理系统正在广阔的市场环境中越扎越稳&#xff0c;成为助力企业数字化转型升级的重要利器设备。想要…

使用PyCharm安装并运行python程序(小白专属教程,建议收藏)

本文将介绍如何使用pycharm安装python环境并运行第一个python程序&#xff0c;适合刚接触python的童鞋参考。 Python的安装 python是一门跨平台的语言&#xff0c;如Windows、Linux、MacOS等平台都能完美兼容&#xff0c;以下只对Windows平台安装做详细介绍。 &#xff11;.…

开创加密资产新纪元:深度解析ERC-314协议

随着加密资产市场的不断发展和区块链技术的日益成熟&#xff0c;新的协议和标准不断涌现&#xff0c;其中包括了ERC-314协议。本文将深入分析ERC-314协议的特点、功能以及对加密资产市场可能产生的影响。 1. ERC-314协议简介 ERC-314协议是一项建立在以太坊区块链上的新提案&a…

鲁大师2024年Q1季度电动车报告:新老品牌角逐电自市场,九号699分夺魁

鲁大师2024年Q1季报正式发布&#xff0c;本次季报包含电动车智能排行&#xff0c;测试的车型为市面上主流品牌的主流车型&#xff0c;共计12款&#xff0c;全部按照评测维度更广、更专业的鲁大师电动车智慧评测2.0进行评分&#xff0c;测试的成绩均来自于鲁大师智慧硬件实验室。…

新规解读 | 被网信办豁免数据出境申报义务的企业,还需要做什么?

为了促进数据依法有序自由流动&#xff0c;激发数据要素价值&#xff0c;扩大高水平对外开放&#xff0c;《促进和规范数据跨境流动规定》&#xff08;以下简称《规定》&#xff09;对数据出境安全评估、个人信息出境标准合同、个人信息保护认证等数据出境制度作出优化调整。 …

QAnything-1.3.0,支持纯python笔记本运行,支持混合检索

QAnything 1.3.0 更新了&#xff0c;这次带来两个主要功能&#xff0c;一个是纯python的安装&#xff0c;另一个是混合检索。更多详情见&#xff1a; https://github.com/netease-youdao/QAnything/releases 纯python安装 我们刚发布qanything开源的时候&#xff0c;希望用户…

冯喜运:4.8晚间黄金原油走势分析及操作建议

黄金走势分析&#xff1a;      金价在亚洲大国市场开盘后突然飙升约30美元至历史新高&#xff0c;触发了交易员的积极反应。这一行情主要是因为亚洲大国央行持续增加黄金储备的预期所致&#xff0c;而且市场对全球央行今年可能的大规模黄金购买提前建立了多头头寸。数据显…

数据转换 | Matlab基于GADF格拉姆角差场一维数据转二维图像方法

目录 效果分析基本介绍程序设计参考资料获取方式 效果分析 基本介绍 GADF&#xff08;Gramian Angular Difference Field&#xff09;是一种将时间序列数据转换为二维图像的方法之一。它可以用于提取时间序列数据的特征&#xff0c;并可应用于各种领域&#xff0c;如时间序列分…

【深入理解Java IO流0x05】Java缓冲流:为提高IO效率而生

1. 引言 我们都知道&#xff0c;内存与硬盘的交互是比较耗时的&#xff0c;因此适当得减少IO的操作次数&#xff0c;能提升整体的效率。 Java 的缓冲流是对字节流和字符流的一种封装&#xff08;装饰器模式&#xff0c;关于IO流中的一些设计模式&#xff0c;后续会再出博客来讲…

详解简单的shell脚本 --- 命令行解释器【Linux后端开发】

首先附上完整代码 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/wait.h> //命令行解释器 //shell 运行原理&#xff1a;通过让子进程执行命令&#xff0c;父进…