09.简单工厂模式与工厂方法模式

道生一,一生二,二生三,三生万物。——《道德经》

在这里插入图片描述
最近小米新车亮相的消息可以说引起了不小的轰动,我们在感慨SU7充满土豪气息的保时捷设计的同时,也深深的被本土品牌的野心和干劲所鼓舞。
今天我们就接着这个背景,开启造车的终极幻想,尝试拆解一下工厂模式中最基础的两部分:简单工厂模式和工厂方法模式。


一言

简单工厂模式:定义一个创建对象的类,由它来封装实例化对象的行为代码。
工厂方法模式:将对象实例化推迟到子类。


为什么要用工厂模式

Wayne造车

如果现在有一个需求,要我们模拟一段造车的代码,你想怎么做?
首先自然是分析需求:

  1. 既然我们要造车,那车的种类必然很多(油车?电车?核动力?!)
  2. 造车的工序我们暂时就粗暴的认为只有准备材料、加工、组装和测试四个步骤
  3. 造好了车,我们还需要通过4S店卖出去

三寸反骨

三条需求刚刚讲完,反骨仔立马站了起来:“这也太简单了!我来!”
于是他这样实现了需求:
首先他清醒的将车做成了抽象:

代码实现(反例)

public abstract class Car {protected String name;//名字//准备原材料,不同的汽车材料不同,所以做成抽象方法public abstract void prepare();public void process(){//加工System.out.println(name+" processing");}public void assemble(){//组装System.out.println(name+" assemble");}public void check(){//测试System.out.println(name+" check");}public void setName(String name) {this.name = name;}
}

然后是车具体的实现:

public class OilCar extends Car{@Overridepublic void prepare() {System.out.println("准备优秀的内燃机");}
}
public class EleCar extends Car{@Overridepublic void prepare() {System.out.println("准备优秀耐用的电池");}
}

最后是4S店

public class FourS {//构造器public FourS() {Car car = null;String orderType;do {orderType=getType();System.out.println("==============================");if (orderType.equals("ele")){car = new EleCar();car.setName("新能源汽车");}else if (orderType.equals("oil")){car = new OilCar();car.setName("燃机汽车");}else {break;}car.prepare();car.process();car.assemble();car.check();}while (true);}private String getType(){try {BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));System.out.println("==============================");System.out.println("input car type");String str = strin.readLine();return str;} catch (IOException e) {e.printStackTrace();}return "";}
}

不得不说,反骨仔确实有所成长,不再是那个100%的毛躁汉子了,但是这种设计是否存在问题?
我们先看下运行的结果:
在这里插入图片描述
业务的实现自然是没有问题的,实现过程也非常容易理解,然后一切的一切发展的都很顺利,我们的车一经上市就大受欢迎,在各方面都是遥遥领先。于是我们决定,扩展业务,“多开几家4S店,再狠狠的赚他一笔,初步预估先开1000家店吧,靓仔啊,你去把这个事情落实一下。奥,对了,你们这个项目现在发展前景非常好,我们已经在和奔驰、宝马、宾利、法拉利等老牌的汽车公司展开了深度合作,以后可能还要把他们的品牌融合到我们的产品中…”。
反骨仔看着自己的代码,汗流浃背了。
可能有的同学已经看到了问题的关键:
在这里插入图片描述
这种设计从根本上违反了OCP原则,每一次小的扩展就会更改大量代码。
有的同学可能会说,我ctrl CV 大法包治百病,那如果我们后面真的在核动力汽车领域有了突破,这部分扩展的代码是不是要改一千多次?
所以说,修改代码并非不可接受,但是如果我们在其它地方也有创建Car,就意味着这些地方都要修改,而创建Car的地方往往有很多处。


基于简单工厂模式的优化

思路分析

好了,我们已经发现了问题下一步就是如何解决这个问题了。
在思路上,我们可以尝试把创建Car对象封装在一个类中,这样我们有新的Car种类时,只需要修改该类即可,其它创建Car对象的代码就不需要修改了。这其实就是简单工厂模式的基本思路。
在这里插入图片描述

核心代码

public class FourS1 {Car car = null;public FourS1(){setFactory();}public void setFactory(){String orderType="";do{orderType = getType();System.out.println("==============================");car = SimpleFactory.createCar(orderType);if (car!=null){car.prepare();car.process();car.assemble();car.check();}else {System.out.println("订购汽车失败");break;}}while (true);}//可以获取客户希望订购的披萨种类private String getType(){try {BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));System.out.println("==============================");System.out.println("input pizza type");String str = strin.readLine();return str;} catch (IOException e) {e.printStackTrace();}return "";}
}

结束了吗

当然没有,我们看似通过简单方法模式解决了大部分的核心问题,但是却忽略了“最新消息”里最致命的那句:“奥,对了,你们这个项目现在发展前景非常好,我们已经在和奔驰、宝马、宾利、法拉利等老牌的汽车公司展开了深度合作,以后可能还要把他们的品牌融合到我们的产品中…”
也就是说,我们后续要求的输出是奔驰的燃机汽车、宝马的燃机汽车、宝马的新能源汽车、奔驰的核动力汽车…
反观简单工厂模式,是否有实力接得住这一波需求?
其实硬要接也不是接不住,无非是多几个SimpleFactory。但是实际操作起来必然很难维护。严格意义上讲,采用简单工厂模式硬接这种需求实际上也是违反OCP原则的。


基于工厂方法模式的优化

思路分析

当与各大品牌合作之后,造车过程似乎变得复杂了起来。首先奔驰和宝马是想和我们合作,而他们之间并没有展开合作,这意味着我们要为他们定制不同的4S店和造车工厂。
在这里插入图片描述

核心代码

public abstract class AbsFourS {public abstract Car createPizza(String orderType);public AbsFourS() {Car car = null;String orderType;do {orderType=getType();System.out.println("==============================");car=createPizza(orderType);car.prepare();car.process();car.assemble();car.check();}while (true);}private String getType(){try {BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));System.out.println("==============================");System.out.println("input car type");String str = strin.readLine();return str;} catch (IOException e) {e.printStackTrace();}return "";}
}
public class BenzWayne4s extends AbsFourS {@Overridepublic Car createPizza(String orderType) {Car car = null;if(orderType.equals("ele")){car = new BenzEleCar();car.setName("奔驰与Wayne联名推出的新能源汽车");}else if (orderType.equals("oil")){car = new BenzOilCar();car.setName("奔驰与Wayne联名推出的内燃机汽车");}return car;}
}
public class BmwWayne4s extends AbsFourS {@Overridepublic Car createPizza(String orderType) {Car car = null;if(orderType.equals("ele")){car = new BMWEleCar();car.setName("宝马与Wayne联名推出的新能源汽车");}else if (orderType.equals("oil")){car = new BMWEleCar();car.setName("宝马与Wayne联名推出的内燃机汽车");}return car;}
}

测试结果

在这里插入图片描述
在这里插入图片描述


我们在前面用了大量的篇幅介绍了简单工厂模式和工厂方法模式。记得我在上一篇介绍建造者模式时,卖了个关子,就是关于建造者模式和抽象工厂模式的区别。
抽象工厂模式可以将简单工厂模式和工厂方法模式的优势整合起来,它的理念是基于简单工厂模式和工厂方法模式的,这也正是我花了大量篇幅介绍它们的原因。
抽象工厂模式实现对产品家族的创建,一个产品家族是具有不同分类维度的产品组合,采用抽象工厂模式不需要关心构建过程,只关心什么产品由什么工厂生产即可。而建造者模式则是要求按照指定的蓝图建造产品,它的主要目的是通过组装零配件而产生一个新产品。
也就是说:
• 建造者模式比较关注 产品的 “组装过程”;
• 抽象工厂模式只关注什么工厂生产了什么产品;
这一点,在我下周继续拆解抽象工厂模式之后,我们可以一起再来体会一下。


关注我,共同进步,每周至少一更。——Wayne

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

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

相关文章

uniapp 解决安卓App使用uni.requestPayment实现沙箱环境支付宝支付报错

背景:uniapp与Java实现的安卓端app支付宝支付,本想先在沙箱测试环境测支付,但一直提示“商家订单参数异常,请重新发起付款。”,接着报错信息就是:{ "errMsg": "requestPayment:fail [pa…

【书生大模型00--开源体系介绍】

书生大模型开源体系介绍 0 通用人工智能1 InternLM性能及模型2 从模型到应用 大模型成为目前很热的关键词,最热门的研究方向,热门的应用;ChatGPT的横空出世所引爆,快速被人们上手应用到各领域; 0 通用人工智能 相信使…

[蓝桥杯学习] 线段树

学习blibli 定义 线段树是一种特殊的平衡二叉查找树,使用线段树,可以实现数据的添加、查找和删除。 树的根结点表示了一个完整的单元区间,左右孩子的区间是将父结点的区间进行二分,左右孩子的区间之和,就是他们的根…

【机器学习】循环神经网络(四)-应用

五、应用-语音识别 5.1 语音识别问题 详述语音识别的经典方法GMMHMM框架 5.2 深度模型 详述DNN-HMM结构 循环神经网络与CTC技术结构用于语音识别问题 六、自然语言处理 RNN-LM建模方法 6.1 中文分词 6.2 词性标注 6.3 命名实体识别 详述LSTMCRF进行命名实体识别的方法 6.4 文本…

ElasticSearch 性能优化

提升写入性能 使用 bulk 接口批量写入 节省重复创建连接的网络开销通过进行基准测试来找到最佳的批处理数量 延长 refresh 的时间间隔 通过延长 refresh(刷新)的时间间隔可以降低段合并的频率,段合并十分耗费资源默认的刷新频率为1s&…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《基于两阶段随机优化的电能量与深度调峰融合市场出清模型及定价方法》

本专栏栏目提供文章与程序复现思路,具体已有的论文与论文源程序可翻阅本博主的专栏栏目《论文与完整程序》 这个标题涉及到一个电力市场的建模和定价方法,采用了两阶段随机优化的策略,目标是实现电能量与深度调峰的融合。下面是对标题中各个…

百度搜索金融:构建高时效、高可用的分布式数据传输系统

作者 | 搜索技术平台研发部 导读 分布式数据传输系统是一种用于在多个计算节点之间高效传输大量数据的系统,诣在高效的解决大规模数据迁移、备份、跨地域复制等问题,其广泛应用在实时数据流传输、跨数据中心数据迁移、多媒体传输等场景,在大多…

智能合约:3分钟开发ERC20 token(2)

0.前言 上一节我们讲到了开发智能合约的准备工作,以及在线编程平台remix 智能合约(1) 这一节讲解如何开发、发行一个代币,并具备包括代币铸造mint,转账transfer和销毁burn功能,并确保合约拥有者owner的权限…

Tracert 与 Ping 程序设计与实现(2024)

1.题目描述 了解 Tracert 程序的实现原理,并调试通过。然后参考 Tracert 程序和计算机网络教材 4.4.2 节, 计算机网络 课程设计指导书 2 编写一个 Ping 程序,并能测试本局域网的所有机器是否在线,运行界面如下图所示的 QuickPing …

【docker】centos 使用 Nexus Repository 搭建私有仓库

Nexus Repository 是一种流行的软件仓库管理工具,它可以帮助您搭建私有仓库,以便在内部网络或私有云环境中存储、管理和分发各种软件包和组件。 它常被用于搭建Maven的镜像仓库。本文演示如何用Nexus Repository搭建docker 私有仓库。 使用Nexus Repos…

毕业设计:基于机器学习xgboost lgbm adaboost 的空气质量预测pm2.5‘, ‘so2‘, ‘no2‘ 完整代码数据-可直接运行

项目详细视频讲解介绍: 基于机器学习xgboost lgbm adaboost 的空气质量预测-完整代码数据可直接运行_哔哩哔哩_bilibili 数据展示: 运行结果展示: 项目代码: from sklearn import preprocessing import random from sklearn.model_selection import train_test_split fr…

《GreenPlum系列》GreenPlum详细入门教程01-GreenPlum介绍

文章目录 第一章 GreenPlum介绍1.MPP架构介绍2.GreenPlum介绍3.GreenPlum数据库架构4.GreenPlum数据库优缺点 GreenPlum:https://cn.greenplum.org/ 第一章 GreenPlum介绍 1.MPP架构介绍 MPP是Massively Parallel Processing的缩写,也就是大规模并行处…

GEE数据集——Cloud Score+ S2_HARMONIZED数据集

简介 Cloud Score 是一种用于中高分辨率光学卫星图像的质量评估(QA)处理器。Cloud Score S2_HARMONIZED数据集是由统一的哨兵-2 L1C数据集制作的,Cloud Score的输出可用于识别相对清晰的像素,并有效去除L1C(大气顶部&…

GPDB - 高可用 - 流复制状态

GPDB - 高可用 - 流复制状态 GPDB的高可用基于流复制,通过FTS进行自动故障切换。自动故障切换需要根据primary-mirror流复制的各种状态进行判断。本节就聊聊primary-mirror流复制的各种状态。同样适用于PgSQL 1、WalSndState typedef enum WalSndState {WALSNDSTATE…

04-微服务-Nacos

Nacos注册中心 国内公司一般都推崇阿里巴巴的技术,比如注册中心,SpringCloudAlibaba也推出了一个名为Nacos的注册中心。 1.1.认识和安装Nacos Nacos是阿里巴巴的产品,现在是SpringCloud中的一个组件。相比Eureka功能更加丰富,在…

MySQL-存储引擎

简介:存储引擎是存储数据,建立索引,更新/查询数据等技术的实现方式。存储引擎是基于表的,而不是基于库的, (同一个数据库的不同表可以选择不同的存储引擎) 所以存储引擎也可被称为表类型。 我们输入 SHOW CREATE TAB…

Halcon机器视觉和运动控制软件通用框架,24年1月最新版新增UI设计器,插件式开发,开箱即用 仅供学习!

24年1月更新 下载点我 此版本已经添加ui设计器。具体功能如上所示,可以自定义变量,写c#脚本,自定义流程,包含了halcon脚本和封装的算子,可自定义ui,通过插件形式开发很方便拓展自己的功能。 ui设计器

消息队列-RocketMQ-概览与搭建

RocketMQ 领域模型 RockeMQ整体结构预览 RocketMQ 中的一些概念 Topic:主题,可以理解为类别、分类的概念 MessageQueue:消息队列,存储数据的一个容器(队列索引数据),默认每个 Topic 下有 4 个队…

AI担任编程导师:生成式AI如何翻江倒海改变开发世界

生成式 AI 如何重塑开发流程和开发工具? 在21世纪的舞台上,AI作为技术明星,一直以其潜力无穷的表现吸引着我们的目光。而其中,一名角色,响亮的名字叫做生成式AI,正在以翩翩起舞的姿态,改变着我…

华为mstp、vrrp、ospf、isis、bgp等综合一起排错

最终实现左边私网和右边私网全部ping通 SW1 vlan batch 12 34 stp region-configuration //mstp配置 region-name test instance 12 vlan 12 instance 34 vlan 34 active region-configuration interface GigabitEthernet0/0/3 port link-type trunk port trunk allow-pass …