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

1. 工厂模式的特点

在海贼王中,作为原王下七武海之一的多弗朗明哥,可以说是新世界最大的流氓头子,拥有无上的权利和无尽的财富。他既是德雷斯罗萨国王又是地下世界的中介,控制着世界各地的诸多产业,人造恶魔果实工厂就是其中之一。
在这里插入图片描述

人造恶魔果实的最大买家是四皇之一的凯多凯多其实很明智,他没有自己去生产,可能有这么几个因素:

  • 凯多手下没有像凯撒·库朗一样的科学家,无法掌握生产人造恶魔果实这种顶级的科学技术【意味着构造一个对象有时候需要经历一个非常复杂的操作流程,既然麻烦那索性就不干了】。
  • 有需求下单就行,只需关心结果,无需关心过程【实现了解耦合】。
  • 人造恶魔果实出了问题,自己无责任,售后直接找明哥【便于维护】。

在我们现实生活中也是一样,买馒头和自己蒸馒头、去饭店点一份大盘鸡和自己养鸡,杀鸡,做大盘鸡,这是全然不同的两种体验:

  • 自己做麻烦,而且有失败的风险,需要自己承担后果。
  • 买现成的,可以忽略制作细节,方便快捷并且无风险,得到的肯定是美味的食物。

对于后者,就相当于是一个加工厂,通过这个工厂我们就可以得到想要的东西,在程序设计中,这种模式就叫做工厂模式,工厂生成出的产品就是某个类的实例,也就是对象。关于工厂模式一共有三种,分别是:简单工厂模式、工厂模式、抽象工厂模式

通过上面人造恶魔果实的例子,我们能够了解到,不论使用哪种工厂模式其主要目的都是实现类与类之间的解耦合,这样我们在创建对象的时候就变成了拿来主义,使程序更加便于维护。在本节中,先介绍简单工厂模式。

基于简单工厂模式去创建对象的时候,需要提供一个工厂类,专门用于生产需要的对象,这样关于对象的创建操作就被剥离出去了。

简单工厂模式相关类的创建和使用步骤如下:

  1. 创建一个新的类, 可以将这个类称之为工厂类。对于简单工厂模式来说,需要的工厂类只有一个。
  2. 在这个工厂类中添加一个公共的成员函数,通过这个函数来创建我们需要的对象,关于这个函数一般将其称之为工厂函数。
  3. 关于使用,首先创建一个工厂类对象,然后通过这个对象调用工厂函数,这样就可以生产出一个指定类型的实例对象了。

2. 生产的产品

在海贼世界中,凯撒·库朗研制的人造恶魔果实是有瑕疵的,吃下人造恶魔果实的失败品没能成功获得果实能力的人,会被剥夺除笑以外的一切表情,所以人造恶魔果实被称为SMILE

在这里插入图片描述

下面是明哥的SMILE工厂要生产的众多人造动物系恶魔果实中的三种:

// 人造恶魔果实· 绵羊形态
class SheepSmile
{
public:void transform(){cout << "变成人兽 -- 山羊人形态..." << endl;}void ability(){cout << "将手臂变成绵羊角的招式 -- 巨羊角" << endl;}
};// 人造恶魔果实· 狮子形态
class LionSmile
{
public:void transform(){cout << "变成人兽 -- 狮子人形态..." << endl;}void ability(){cout << "火遁· 豪火球之术..." << endl;}
};// 人造恶魔果实· 蝙蝠形态
class BatSmile
{
public:void transform(){cout << "变成人兽 -- 蝙蝠人形态..." << endl;}void ability(){cout << "声纳引箭之万剑归宗..." << endl;}
};

不论是吃了那种恶魔果实,获得了相应的能力之后,可以做的事情大体是相同的,那就是形态变化transform() 和 使用果实能力alility()

另外,生产这些恶魔果实的时候可能需要极其复杂的参数,在此就省略了【也就是说这些类的构造函数的参数在此被省略了】。

3. 如何生产

如果想要生产出这些恶魔果实,可以先创建一个工厂类,然后再给这个工厂类添加一个工厂函数,又因为我们要生成三种不同类型的恶魔果实,所以可以给工厂函数添加一个参数,用以控制当前要生产的是哪一类。

enum class Type:char{SHEEP, LION, BAT};
// 恶魔果实工厂类
class SmileFactory
{
public:enum class Type:char{SHEEP, LION, BAT};SmileFactory() {}~SmileFactory() {}void* createSmile(Type type){void* 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;}
};int main()
{SmileFactory* factory = new SmileFactory;BatSmile* batObj = (BatSmile*)factory->createSmile(Type::BAT);return 0;
}
  • 关于恶魔果实的类型,上面的类中用到了强类型枚举(C++11新特性),增强了代码的可读性,并且将枚举元素设置为了char类型,节省了内存。
  • 函数createSmile(Type type)的返回值是void*类型,这样处理主要是因为每个case 语句创建出的对象类型是不一样的,为了实现兼容,故此这样处理。
  • 得到函数createSmile(Type type)的返回值之后,还需要将其转换成实际的类型,处理起来还是比较繁琐的。
    关于工厂函数的返回值,在C++中还有一种更好的解决方案,就是使用多态。如果想要实现多态,需要满足三个条件:
  • 类和类之间有继承关系。
  • 父类中有虚函数,并且在子类中需要重写这些虚函数。
  • 使用父类指针或引用指向子类对象。

所以,我们需要给人造恶魔果实提供一个基类,然后让上边的三个类SheepSmile、LionSmile、BatSmile作为子类继承这个基类。根据分析我们就有画出简单工厂模式的UML类图了:

在这里插入图片描述

根据UML类图,编写出的代码如下:

#include <iostream>
using namespace std;class AbstractSmile
{
public:virtual void transform() {}virtual void ability() {}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;}
};// 恶魔果实工厂类
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;}
};int main()
{SmileFactory* factory = new SmileFactory;AbstractSmile* obj = factory->createSmile(Type::BAT);obj->transform();obj->ability();return 0;
}

通过上面的代码,我们实现了一个简单工厂模式,关于里边的细节有以下几点需要说明:

  1. 由于人造恶魔果实类有继承关系, 并且实现了多态,所以父类的析构函数也应该是虚函数,这样才能够通过父类指针或引用析构子类的对象。

  2. 工厂函数createSmile(Type type)的返回值修改成了AbstractSmile*类型,这是人造恶魔果实类的基类,通过这个指针保存的是子类对象的地址,这样就实现了多态,所以在main()函数中,通过obj对象调用的实际是子类BatSmile中的函数,因此打印出的信息应该是这样的:

变成人兽 -- 蝙蝠人形态...
声纳引箭之万剑归宗...

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

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

相关文章

基于springboot实现校园资料分享平台系统项目【项目源码+论文说明】

基于springboot实现校园资料分享平台系统演示 摘要 随着信息互联网购物的飞速发展&#xff0c;国内放开了自媒体的政策&#xff0c;一般企业都开始开发属于自己内容分发平台的网站。本文介绍了校园资料分享平台的开发全过程。通过分析企业对于校园资料分享平台的需求&#xff…

吴恩达深度学习笔记:深层神经网络(Deep Neural Networks)4.1-4.4

目录 第一门课&#xff1a;神经网络和深度学习 (Neural Networks and Deep Learning)第四周&#xff1a;深层神经网络(Deep Neural Networks)4.1 深层神经网络&#xff08;Deep L-layer neural network&#xff09;4.2 前向传播和反向传播&#xff08;Forward and backward pro…

“逃离”OpenAI!36人出走,已拿600亿融资

“逃离”OpenAI&#xff01;36人出走&#xff0c;已拿600亿融资© 由 智东西 提供 智东西 作者 | 程茜 编辑 | 心缘 最近OpenAI频繁高薪挖人&#xff0c;把马斯克惹毛了。 马斯克在社交平台X上公开爆料&#xff1a;OpenAI一直在高薪挖特斯拉工程师&#xff0c;甚至还想…

四、书城开发-2、热门搜索/推荐页面的开发

热门搜索的开发 热门搜索页面的交互主要有4个交互点 第一个交互是点击搜索框时&#xff0c;热门搜索会渐影显示&#xff1b;第二个交互是点击返回图标时热门搜索会渐影消失&#xff1b;第三个交互是热门搜索滑动页面的时候搜索栏下面会出现阴影&#xff0c;回到顶部时阴影会消…

深入浅出 -- 系统架构之微服务标准组件及职责

我们来认识一下微服务架构在Java体系中依托哪些组件实现的。 相对于单体架构的简单粗暴&#xff0c;微服务的核心是将应用打散&#xff0c;形成多个独立提供的微服务&#xff0c;虽然从管理与逻辑上更符合业务需要。但微服务架构也带来了很多急需解决的核心问题&#xff1a; 1…

PDF锐化

PDF Shaper Ultimate(pdf转图片) 编辑->添加文件->选中一个要处理的pdf 操作->转换->PDF转为图片 ComicEnhancerPro设置(把图片锐化) PDF Shaper Ultimate(图片转pdf) 编辑-添加图片->选中所有锐化处理后的图片 转换->图片转为pdf&#xff08;会把所有图…

最新AI工具系统ChatGPT网站运营源码SparkAi系统V6.0版本,GPTs应用、AI绘画、AI换脸、垫图混图、Suno-v3-AI音乐生成大模型全支持

一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧。已支持GPT…

《深入Linux内核架构》第4章 进程虚拟内存(2)

目录 4.3 内存映射原理 4.4 数据结构 4.4.1 树和链表 4.4.2 虚拟内存区域VMA的表示 4.4.3 相关数据结构 本节讲VMA结构体struct vm_area_struct和struct address_space。 4.3 内存映射原理 所有进程的虚拟空间总和比物理内存大得多&#xff0c;因此只有最常用的虚拟空间…

生活日常韩语成人外语培训中为什么韩国人说话喜欢用“~도록”?

많이 받는 질문 중 하나가 ‘~도록’을 자신에게 쓸 수 있는가 하는 것이다. 즉 “제가 하도록 하겠습니다” “조심하도록 하겠습니다” “말씀드리도록 하겠습니다” 등과 같은 표현이다. 我经常被问到的问题之一就是能否将“~도록”用于自己。比如“我来做吧”、“我会小心…

深度学习500问——Chapter06: 循环神经网络(RNN)(2)

文章目录 6.4 CNN和RNN的区别 6.5 RNNs与FNNs有什么区别 6.6 RNNs训练和传统ANN训练异同点 6.7 为什么RNN训练的时候Loss波动很大 6.8 标准RNN前向输出流程 6.9 BPTT算法推导 6.9 RNN中为什么会出现梯度消失 6.10 如何解决RNN中的梯度消失问题 6.4 CNN和RNN的区别 类别特点描述…

sfml sdl2 windows vscode 调试和coderunner插件运行

链接库写在编译链接命令里&#xff0c;如果没有使用到不会加入到生成的可执行文件里。所以tasks.json可以这样写&#xff0c; {"version": "2.0.0","tasks": [{"type": "cppbuild","label": "C/C: g.exe 生…

Apache Pulsar源码解析之Lookup机制

文章目录 引言Lookup是什么客户端实现原理服务端实现原理总结 引言 在学习Pulsar一段时间后&#xff0c;相信大家也或多或少听说Lookup这个词&#xff0c;今天就一起来深入剖析下Pulsar是怎么设计的它吧 Lookup是什么 在客户端跟服务端建立TCP连接前有些信息需要提前获取&am…

arm-linux-gnueabihf-gcc默认目录

默认编译的头文件目录&#xff1a; /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/lib 默认编译的库文件目录&#xff1a; /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/include/ …

vscode 重命名很慢或失败 vscode renames are slow

网上问题&#xff0c; 插件问题&#xff08;我遇见的排除&#xff0c;不是&#xff09;被其他程序占用问题&#xff0c;&#xff08;我这边是这个&#xff09; 解决方案&#xff1a; 打开【资源管理器】&#xff0c;使用火绒 或其他软件&#xff0c;查看文件夹 or 文件 被哪个…

2024.4.9-day12-CSS 常用样式属性和字体图标

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 作业 作业 <!DOCTYPE html> <html lang"zh-CN"><he…

go之web框架gin

介绍 Gin 是一个用 Go (Golang) 编写的 Web 框架。 它具有类似 martini 的 API&#xff0c;性能要好得多&#xff0c;多亏了 httprouter&#xff0c;速度提高了 40 倍。 如果您需要性能和良好的生产力&#xff0c;您一定会喜欢 Gin。 安装 go get -u github.com/gin-gonic/g…

【C++】unordered 系列关联式容器

文章目录 1. unordered 系列关联式容器2. unordered_map2.1 unordered_map 的文档介绍2.2 unordered_map 的接口说明 3. unordered_set4. 在线 OJ 1. unordered 系列关联式容器 在 C 98 中&#xff0c;STL 提供了底层为红黑树结构的一系列关联式容器&#xff0c;在查询时效率可…

STM32中C编程引入C++程序

C具备类的创建思想很实用于实际场景多相似性的框架搭建&#xff1b;同种类型或相似类型的C的优势明显因此进行相互嵌套使用 需要在C中使用C类的话&#xff0c;你可以通过C的“extern "C"”语法来实现。这允许你在C代码中使用C的链接方式&#xff0c;而在C代码中使用…

实现RAG:使用LangChain实现图检索查询

你是不是有时会遇到这样的问题&#xff1a;你可能遇到的任何主题或问题&#xff0c;都有大量的文档&#xff0c;但是当尝试将某些内容应用于自己的用途时&#xff0c;突然发现很难找到所需的内容。 在这篇博文中&#xff0c;我们将看一下LangChain是如何实现RAG的&#xff0c;这…

kali基础渗透学习,永恒之蓝,木马实战

简介 kali的学习本质是在linux上对一些攻击软件的使用&#xff0c;只是学习的初期 先在终端切换到root用户&#xff0c;以便于有些工具对权限的要求 下载链接 镜像源kali 攻击流程 公网信息搜集 寻找漏洞&#xff0c;突破口&#xff0c;以进入内网 进入内网&#xff0c…