设计模式——工厂三兄弟之简单工厂
1.业务需求
大家好,我是菠菜。在介绍这期简单工厂设计模式前,我们先来看看这样的需求:制作一个简单的计算器,能够实现控制台输入俩个数以及运算符完成运算。

2.初步实现
实现第一版思路:
创建计算器类,控制台输入俩个数以及运算符,通过if条件输出运算结果。
CalClient 类:
public class CalClient {public static void main(String[] args) {Scanner sc=new Scanner(System.in);System.out.println("请输入第一个数:");double numbera=sc.nextDouble();System.out.println("请输入运算符:");String operator=sc.next();System.out.println("请输入第二个数:");double numberb=sc.nextDouble();if("+".equals(operator)){System.out.println("运算结果为:"+(numbera+numberb));}else if("-".equals(operator)){System.out.println("运算结果为:"+(numbera-numberb));}else if("*".equals(operator)){System.out.println("运算结果为:"+(numbera*numberb));}else if("/".equals(operator)){if(numberb==0){System.out.println("除数不能为零");return;}System.out.println("运算结果为:"+(numbera/numberb));}}
}
思考:这段代码在当时初学编程来说,没有问题,而且结果都能执行成功并输出。但是现在我们再来看是不是有点不太满意的地方,比如:计算控制台逻辑和计算方法逻辑耦合在一起,不满足上一期我们所学的单一职责原则,于是我又优化了一版。
实现第二版思路:
增加Operation运算类,将计算方法封装到里面,把计算控制台逻辑和计算方法拆开,降低耦合。
Operation类:
public class Operation {public static Double getOperationResult(double numbera,double numberb,String operator){Double result=null;switch (operator){case "+":result=numbera+numberb;break;case "-":result=numbera-numberb;break;case "*":result=numbera*numberb;break;case "/":if(numberb==0){System.out.println("除数不能为零");return result;}result=numbera/numberb;break;}return result;}
}
CalClient类:
public class CalClient {public static void main(String[] args) {Scanner sc=new Scanner(System.in);System.out.println("请输入第一个数:");double numbera=sc.nextDouble();System.out.println("请输入运算符:");String operator=sc.next();System.out.println("请输入第二个数:");double numberb=sc.nextDouble();//2.将业务逻辑和界面逻辑分开 解耦System.out.println("运算结果为:"+(Operation.getOperationResult(numbera,numberb,operator)));}
}
**思考:**上述代码,虽然将控制台和计算方法解耦,而且这个计算方法类可以做到一定程度上的复用,但是又有了一些新的问题:后续添加或修改计算方法要修改整个Operation类并编译,不安全而且会影响到正常运行的代码,而且该设计没有面向对象编程。我思考了一下,于是就有了下一个升级版本。
3.方案改进
实现第三版本思路:
增加类OperationFactory,用于实例化具体的计算实例。增加抽象类AOpeartion,提取统一计算方法。增加计算实现类OperationAdd、OperationSub、OperationMul、OperationDiv。

OperationFactory类:
public class OperationFactory {public static AOpeartion createOperation(String operator){AOpeartion opeartion=null;switch (operator){case "+":opeartion=new OperationAdd();break;case "-":opeartion=new OperationSub();break;case "*":opeartion=new OperationMul();break;case "/":opeartion=new OperationDiv();break;}return opeartion;}
}
AOpeartion类:
public abstract class AOpeartion {public abstract Double getOperationResult(double numbera, double numberb);
}
OperationAdd类:
public class OperationAdd extends AOpeartion {@Overridepublic Double getOperationResult(double numbera, double numberb) {return numbera+numberb;}
}
OperationSub类:
public class OperationSub extends AOpeartion {@Overridepublic Double getOperationResult(double numbera, double numberb) {return numbera-numberb;}
}
OperationMul类:
public class OperationMul extends AOpeartion {@Overridepublic Double getOperationResult(double numbera, double numberb) {return numbera*numberb;}
}
OperationDiv类:
public class OperationDiv extends AOpeartion {@Overridepublic Double getOperationResult(double numbera, double numberb) {if(numberb==0){System.out.println("除数不能为零");return null;}return numbera/numberb;}
}
CalClient类:
public class CalClient {public static void main(String[] args) {Scanner sc=new Scanner(System.in);System.out.println("请输入第一个数:");double numbera=sc.nextDouble();System.out.println("请输入运算符:");String operator=sc.next();System.out.println("请输入第二个数:");double numberb=sc.nextDouble();//3.利用简单工厂实现 易维护 易复用 易拓展AOpeartion opeartion=OperationFactory.createOperation(operator);if(null!=opeartion){System.out.println("运算结果为:"+(opeartion.getOperationResult(numbera,numberb)));}else{System.out.println("运算工厂获取运算类失败");}}
}
思考:OperationFactory工厂类通过输入的运算符去实例化相应合适的对象,通过多态返回父类的方式实现了计算器的结果。后续如果修改具体的计算方法只要修改具体的计算类即可,不会影响其它计算类。如果增加计算方法,增加实现相应的计算类的具体子类以及增加计算工厂类的switch分支即可。
4.定义和组成结构
工厂模式的定义:定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。按实际业务场景划分,工厂模式有 3 种不同的实现方式,分别是简单工厂模式、工厂方法模式和抽象工厂模式。我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”。在简单工厂模式中创建实例的方法通常为静态(static)方法,因此简单工厂模式(Simple Factory Pattern)又叫作静态工厂方法模式(Static Factory Method Pattern)。
简单工厂模式的主要角色如下:
简单工厂(SimpleFactory):是简单工厂模式的核心,负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。
抽象产品(AbstractProduct):是简单工厂创建的所有对象的父类,负责描述所有实例共有的公共接口。
具体产品(ConcreteProduct):是简单工厂模式的具体创建目标。

5.优缺点以及应用场景
优点:
- 简单工厂模式实现了对象创建和使用的分离,职责分明
- 客户端无需知道所创建具体对象的类名,只需知道参数即可
缺点:
- 工厂类集中了所有产品的创建逻辑,职责过重
- 系统扩展困难,添加新产品要修改原有逻辑,违反了开闭原则,产品种类一多,工厂类逻辑过于复杂,不利有扩展和维护
应用场景: 对于产品种类相对较少的情况,考虑使用简单工厂模式。使用简单工厂模式的客户端只需要传入工厂类的参数,不需要关心如何创建对象的逻辑,可以很方便地创建所需产品。
友情提示:请尊重作者劳动成果,如需转载本博客文章请注明出处!谢谢合作!
【作者:我爱吃菠菜 个人博客地址】
相关文章:
设计模式——工厂三兄弟之简单工厂
1.业务需求 大家好,我是菠菜。在介绍这期简单工厂设计模式前,我们先来看看这样的需求:制作一个简单的计算器,能够实现控制台输入俩个数以及运算符完成运算。 2.初步实现 实现第一版思路: 创建计算器类&…...
如何使用ChatGPT撰写短视频爆款文案
在这个快速发展的数字时代,短视频已经成为最受欢迎的娱乐和信息获取方式之一。对于内容创作者来说,如何制作出爆款短视频,吸引更多观众的注意力,是他们面临的一大挑战。文案,作为视频内容的灵魂,起着至关重…...
申办风景园林设计乙级资质如何整理技术人员的专业培训证明
整理技术人员的专业培训证明是申办风景园林设计乙级资质的重要环节,它直接关系到证明技术人员持续学习和专业能力提升的情况。以下是整理专业培训证明的一些建议步骤: 收集培训记录:首先,向所有参与设计工作的技术人员收集他们参加…...
类别型特征
#机器学习 #深度学习 #基础知识 #特征工程 #数据编码 背景 在现实生活中,我们面对的数据类型有很多,其中有的数据天然为数值类型具备数值意义,那么可以很自然地和算法结合,但是大部分数据他没有天然的数值意义,那么将他们送入到算法前,就需要对数据进行编码处理,将其转换为数…...
java医院管理系统源码(springboot+vue+mysql)
风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的医院管理系统。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: 医院管理系统的主要使用者分…...
vue2 面试题
一、.vue的性能优化怎么做? 1.编码优化: 不要把所有的数据都放在data中;v-for时给每个元素绑定事件用事件代理;keep-alive缓存组件;尽可能拆分组件,提高复用性、维护性;key值要保证唯一&#…...
【JavaEE精炼宝库】多线程(3)线程安全 | synchronized
目录 一、线程安全 1.1 经典线程不安全案例: 1.2 线程安全的概念: 1.3 线程不安全的原因: 1.3.1 案例刨析: 1.3.2 线程不安全的名词解释: 1.3.3 Java 内存模型 (JMM): 1.3.4 解决线程不安全问题: 二…...
el-table-column两种方法处理特殊字段,插槽和函数
问题:后端返回的字段为数字 解决办法: {{ row[item.prop] 1 ? "启用" : "禁用" }} {{ row[item.prop] }} 最终果: 另外:如果多种状态时可用函数 {{ getStatus(row[item.prop]) }} {{ row[item.prop…...
huggingface笔记: accelerate estimate-memory 命令
探索可用于某一机器的潜在模型时,了解模型的大小以及它是否适合当前显卡的内存是一个非常复杂的问题。为了缓解这个问题,Accelerate 提供了一个 命令行命令 accelerate estimate-memory。 accelerate estimate-memory {MODEL_NAME} --library_name {LIBR…...
李飞飞亲自撰文:大模型不存在主观感觉能力,多少亿参数都不行
近日,李飞飞连同斯坦福大学以人为本人工智能研究所 HAI 联合主任 John Etchemendy 教授联合撰写了一篇文章,文章对 AI 到底有没有感觉能力(sentient)进行了深入探讨。 「空间智能是人工智能拼图中的关键一环。」知名「AI 教母」李…...
超级好用的C++实用库之套接字
💡 需要该C实用库源码的大佬们,可搜索微信公众号“希望睿智”。添加关注后,输入消息“超级好用的C实用库”,即可获得源码的下载链接。 概述 C中的Socket编程是实现网络通信的基础,允许程序通过网络与其他程序交换数据。…...
C++ | Leetcode C++题解之第108题将有序数组转换为二叉搜索树
题目: 题解: class Solution { public:TreeNode* sortedArrayToBST(vector<int>& nums) {return helper(nums, 0, nums.size() - 1);}TreeNode* helper(vector<int>& nums, int left, int right) {if (left > right) {return nu…...
5月27日,每日信息差
第一、韩国宇宙航空厅于 5 月 27 日正式成立,旨在推动以民间为主的太空产业生态圈发展,助力韩国成为航天强国。首任厅长尹宁彬表示,该机构将在庆尚南道泗川市的临时大楼开展相关工作。 第二、京东集团宣布,自2024年7月1日起&…...
echart扩展插件词云echarts-wordcloud
echart扩展插件词云echarts-wordcloud 一、效果图二、主要代码 一、效果图 二、主要代码 // 安装插件 npm i echarts-wordcloud -Simport * as echarts from echarts; import echarts-wordcloud; //下载插件echarts-wordcloud import wordcloudBg from /components/wordcloudB…...
解决无法直接抓取链接地址
当我们在爬取一些文章列表的时候,可能无法从接口或者html界面上获取到文章的详细列表 这个时候我们可以通过模拟点击且重写window.open方法,将跳转的地址捕获,并且放到html中去。 这样我们就可以获取到某个文章的详细地址了 // 保存原始的 …...
java面对对象编程-多态
介绍 方法的多态 多态是在继承,重载,重写的基础上实现的 我们可以看看这个代码 package b;public class main_ {public static void main(String[] args) { // graduate granew graduate(); // gra.cry();//这个时候,子类的cry方法就重写…...
【Sql Server】随机查询一条表记录,并重重温回顾下自定义函数的封装和使用
大家好,我是全栈小5,欢迎来到《小5讲堂》。 这是《Sql Server》系列文章,每篇文章将以博主理解的角度展开讲解。 温馨提示:博主能力有限,理解水平有限,若有不对之处望指正! 目录 前言随机查询语…...
基于C#开发web网页管理系统模板流程-主界面管理员录入和编辑功能完善
前言 紧接上篇->基于C#开发web网页管理系统模板流程-登录界面和主界面_c#的网页编程-CSDN博客 已经完成了登录界面和主界面,本篇将完善主界面的管理员录入和编辑功能,事实上管理员录入和编辑的设计套路适用于所有静态表的录入和编辑 首先还是介绍一下…...
K8s证书过期处理
问题描述 本地有一个1master2worker的k8s集群,今天启动VMware虚拟机之后发现api-server没有起来,docker一直退出,这个集群是使用kubeadm安装的。 于是kubectl logs查看了日志,发现证书过期了 解决方案: 查看证书 #…...
刷题之路径总和Ⅲ(leetcode)
路径总和Ⅲ 这题和和《为K的数组》思路一致,也是用前缀表。 代码调试过,所以还加一部分用前序遍历数组和中序遍历数组构造二叉树的代码。 #include<vector> #include<unordered_map> #include<iostream> using namespace std; //Def…...
国产化服务器上,手把手教你用TongHttpServer V6.0搭建静态资源站(含麒麟/统信系统适配指南)
国产化环境实战:TongHttpServer V6.0静态资源站部署全攻略 在信创产业快速发展的背景下,国产化软硬件生态已逐步成熟。对于需要在国产CPU和操作系统环境中部署Web服务的工程师而言,选择一款性能优异且兼容性良好的国产Web服务器软件至关重要。…...
从零构建:基于OpenCV与人体姿态分析的跌倒检测实战(附完整源码)
1. 为什么我们需要跌倒检测系统 想象一下家里的老人独自在客厅活动时突然摔倒的场景。这种意外在现实生活中并不罕见,尤其是对于行动不便的老年人群体。传统的解决方案往往依赖于佩戴式设备或紧急呼叫按钮,但这些方法要么需要用户主动操作,要…...
ai赋能设计:超越传统ps软件下载,用快马打造你的智能图像创作助手
AI赋能设计:超越传统PS软件下载,用快马打造你的智能图像创作助手 传统PS软件下载后,设计师往往需要花费大量时间在重复性操作上。而现在,通过InsCode(快马)平台结合AI模型,我们可以打造一个全新的智能图像创作助手&am…...
从WPF迁移到Avalonia:开发者必须掌握的12个关键差异与实战转换指南
1. 文件格式与样式系统的根本差异 如果你是从WPF转向Avalonia的老手,第一个迎面而来的变化就是文件扩展名。在WPF中我们熟悉的.xaml文件,在Avalonia中变成了.axaml。这个小小的"a"前缀背后,其实隐藏着框架设计理念的重大转变。我刚…...
C++高性能网络库ZLToolKit资源池源码解析:如何用智能指针实现对象复用与自动回收
C高性能网络库ZLToolKit资源池源码解析:智能指针实现对象复用与自动回收 在C高性能服务器开发中,频繁的对象创建与销毁往往是性能瓶颈之一。想象一下这样的场景:一个直播服务器每秒需要处理数万条消息,每条消息都需要临时创建对象…...
MySQL服务从CentOS7迁移到Rocky Linux 9.4实施文档
一、文档概述 本文档针对CentOS 7系统上运行的MySQL服务迁移至Rocky Linux 9.4的完整实施流程进行说明,适用于生产环境下MySQL 5.7/8.0版本的迁移操作,涵盖迁移前准备、迁移执行、验证、回滚全流程,可有效控制迁移风险,保障业务连续性。 本次迁移可选两种方案:原地升级迁…...
实战指南:利用快马平台为不同项目类型智能定制idea开发环境与工具链
今天想和大家分享一个实战经验:如何根据不同项目类型,快速定制专属的IDEA开发环境。作为开发者,我们经常需要切换不同技术栈,每次手动安装插件、配置SDK的过程实在太费时间。最近发现用InsCode(快马)平台可以智能解决这个问题&…...
从‘发快递’到‘收快递’:手把手拆解RocketMQ 5.x中Group、Topic、Queue的实战配置与避坑指南
从‘发快递’到‘收快递’:手把手拆解RocketMQ 5.x中Group、Topic、Queue的实战配置与避坑指南 想象一下你正在搭建一个电商系统,订单创建后需要实时通知库存服务扣减库存、支付服务生成账单、物流服务准备发货。这种异步解耦的场景正是消息队列的用武之…...
OpenClaw网页前端开发与优化全流程指南
OpenClaw网页前端开发与优化全流程指南 🌐 核心价值:OpenClaw实现"需求→设计→代码→优化→部署"全流程自动化,开发效率提升600%,页面加载速度提升300%,SEO评分提升85%,完全兼容React/Vue/Angul…...
用STM32F103C8T6和NRF24L01自制遥控器,从硬件选型到代码调试的完整避坑指南
STM32F103C8T6与NRF24L01遥控器开发实战:从硬件设计到软件调试的全流程解析 在创客和嵌入式开发领域,无线遥控系统一直是热门话题。无论是机器人控制、无人机飞行还是智能家居应用,稳定可靠的遥控器都是不可或缺的核心组件。本文将详细介绍如…...
