当前位置: 首页 > news >正文

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

相关文章:

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

道生一,一生二,二生三,三生万物。——《道德经》 最近小米新车亮相的消息可以说引起了不小的轰动,我们在感慨SU7充满土豪气息的保时捷设计的同时,也深深的被本土品牌的野心和干劲所鼓舞。 今天我们就接着这个背景&…...

DHCP,怎么在Linux和Windows中获得ip

一、DHCP 1.1 什么是dhcp DHCP动态主机配置协议,通常被应用在大型的局域网络环境中,主要作用是集中地管理、分配IP地址,使网络环境中的主机动态的获得IP地址、DNS服务器地址等信息,并能够提升地址的使用率。 DHCP作为用应用层协…...

读写锁(arm)

参考文章读写锁 - ARM汇编同步机制实例(四)_汇编 prefetchw-CSDN博客 读写锁允许多个执行流并发访问临界区。但是写访问是独占的。适用于读多写少的场景 另外好像有些还区分了读优先和写优先 读写锁定义 typedef struct {arch_rwlock_t raw_lock; #if…...

【第33例】IPD体系进阶:市场细分

目录 内容简介 市场细分原因 市场细分主要活动 市场细分流程 作者简介 内容简介 这节内容主要来谈谈 IPD 市场管理篇的市场细分步骤。 其中,市场管理(Market Management)是一套系统的方法。 用于对广泛的机会进行选择性收缩,...

response 拦截器返回的二进制文档(同步下载excel)如何配置

response 拦截器返回的二进制文档(同步下载excel)如何配置 一、返回效果图二、response如何配置 一、返回效果图 二、response如何配置 service.interceptors.response.use(response > {// 导出excel接口if (response.config.isExport) {return resp…...

为什么要使用云原生数据库?云原生数据库具体有哪些功能?

相比于托管型关系型数据库,云原生数据库极大地提高了MySQL数据库的上限能力,是云数据库划代的产品;云原生数据库最早的产品是AWS的 Aurora。AWS Aurora提出来的 The log is the database的理念,实现存储计算分离,把大量…...

05- OpenCV:图像操作和图像混合

目录 一、图像操作 1、读写图像 2、读写像素 3、修改像素值 4、Vec3b与Vec3F 5、相关的代码演示 二、图像混合 1、理论-线性混合操作 2、相关API(addWeighted) 3、代码演示(完整的例子) 一、图像操作 1、读写图像 (1)…...

人脸识别(Java实现的)

虹软人脸识别&#xff1a; 虹软人脸识别的地址&#xff1a;虹软视觉开放平台—以免费人脸识别技术为核心的人脸识别算法开放平台 依赖包&#xff1a; 依赖包是从虹软开发平台下载的 在项目中引入这个依赖包 pom.xml <!-- 人脸识别 --><dependency><gr…...

Maven 依赖管理项目构建工具 教程

Maven依赖管理项目构建工具 此文档为 尚硅谷 B站maven视频学习文档&#xff0c;由官方文档搬运而来&#xff0c;仅用来当作学习笔记用途&#xff0c;侵删。 另&#xff1a;原maven教程短而精&#xff0c;值得推荐&#xff0c;下附教程链接。 atguigu 23年Maven教程 目录 文章目…...

供应链+低代码,实现数字化【共赢链】转型新策略

在深入探讨之前&#xff0c;让我们首先明确供应链的基本定义。供应链可以被理解为一个由采购、生产、物流配送等环节组成的网状系统&#xff0c;它始于原材料的采购&#xff0c;经过生产加工&#xff0c;最终通过分销和零售环节到达消费者手中。 而数字化供应链&#xff0c;则是…...

[力扣 Hot100]Day3 最长连续序列

题目描述 给定一个未排序的整数数组 nums &#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 出处 思路 此题可用带排序的哈希表&#xff0c;先构建哈希表&#xff0…...

【办公技巧】Word功能区灰色显示不能编辑,怎么破?

Word文档可以设置加密来保护文件禁止修改&#xff0c;但是在word文档中设置限制编辑功能时对它的作用是否有详细的了解呢&#xff1f;今天为大家介绍word限制编辑功能的作用以及忘记了限制编辑密码该如何解决。 设置限制大家应该都清楚&#xff0c;就是点击工具栏中的审阅 – …...

全志V853开发板原理图

本章节将对开发板几个主要的部件的原理图进行说明&#xff0c;方便快速上手开发板的硬件资料。 开发板硬件框图如下&#xff1a; 模块介绍 GPIO 分配 此表格为 V853 部分重要的 GPIO 的分配表&#xff0c;> 表示对IO的另外一个复用&#xff0c;完整的 GPIO 分配请参阅原理…...

【解决】Unity Project 面板资源显示丢失的异常问题处理

开发平台&#xff1a;Unity 2021.3.7f1c1   一、问题描述 在开发过程中&#xff0c;遭遇 Project 面板资源显示丢失、不全的问题。但 Unity Console 并未发出错误提示。   二、解决方案&#xff1a;删除 Library 目录 前往 “工程目录/Library” 删除内部所有文件并重打开该…...

Hyperledger Fabric Docker 方式多机部署生产网络

规划网络拓扑 3 个 orderer 节点&#xff1b;组织 org1 , org1 下有两个 peer 节点&#xff0c; peer0 和 peer1; 组织 org2 , org2 下有两个 peer 节点&#xff0c; peer0 和 peer1; 因为我只有 3 台虚拟机资源所以没法实现完全的多机部署&#xff0c;资源使用规划如下&#…...

高效降压控制器FP7132XR:为高亮度LED提供稳定可靠的电源

目录 一. FP7132概述 二. 驱动电路&#xff1a;FP7132 三. FP7132应用 高亮度LED作为新一代照明技术的代表&#xff0c;已经广泛应用于各种领域。然而&#xff0c;高亮度LED的工作电压较低&#xff0c;需要一个高效降压控制器来为其提供稳定可靠的电源。在众多降压控制器…...

Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent

文章目录 Pre概述Code源码分析 Pre Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent 概述 Spring Boot 的广播机制是基于观察者模式实现的&#xff0c;它允许在 Spring 应用程序中发布和监听事件。这种机制的主要目的是为了实现解耦&#…...

华为HCIE课堂笔记第十三章 IPv6地址配置

目录 第十三章 IPv6地址配置 13.1 IPv6地址无状态自动配置 13.1.1 RS和RA报文格式 13.1.2 RA的Flags字段 13.1.3 地址的生存周期 13.1.4 RA报文中前缀中的Flags 13.2 DHCPv6 13.2.1 DHCPV6的概念 13.2.2 DCHPv6的报文 第十三章 IPv6地址配置 13.1 IPv6地址无状态自动…...

计算机网络-VLAN间通信

之前复习了VLAN的概念以及几个接口类型。VLAN在二层可以实现广播域的划分&#xff0c;VLAN间可以实现二层通信&#xff0c;但是不能实现三层通信&#xff0c;需要借助其它方式。 一、概述 实际网络部署中一般会将不同IP地址段划分到不同的VLAN。同VLAN且同网段的PC之间可直接进…...

vue3的福音框架arco.design

前言&#xff1a; 在vue2于2023年底正式宣布不在维护&#xff0c;vue3使用越来越频繁的时刻&#xff0c;我们实现项目的辅助框架也越来越多。element, iview, antd 等经典框架继续风靡一时&#xff0c;不过也有很多好的框架&#xff0c;功能也强大&#xff0c;比如我们今天说的…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...

《C++ 模板》

目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板&#xff0c;就像一个模具&#xff0c;里面可以将不同类型的材料做成一个形状&#xff0c;其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式&#xff1a;templa…...

SpringAI实战:ChatModel智能对话全解

一、引言&#xff1a;Spring AI 与 Chat Model 的核心价值 &#x1f680; 在 Java 生态中集成大模型能力&#xff0c;Spring AI 提供了高效的解决方案 &#x1f916;。其中 Chat Model 作为核心交互组件&#xff0c;通过标准化接口简化了与大语言模型&#xff08;LLM&#xff0…...

五子棋测试用例

一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏&#xff0c;有着深厚的文化底蕴。通过将五子棋制作成网页游戏&#xff0c;可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家&#xff0c;都可以通过网页五子棋感受到东方棋类…...

【深度学习新浪潮】什么是credit assignment problem?

Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…...