设计模式—简单工厂
目录
一、前言
二、简单工厂模式
1、计算器例子
2、优化后版本
3、结合面向对象进行优化(封装)
3.1、Operation运算类
3.2、客户端
4、利用面向对象三大特性(继承和多态)
4.1、Operation类
4.2、加法类
4.3、减法类
4.4、乘法类
4.5、除法类
4.6、简单工厂
4.7、客户端
5、简单工厂模式优点
6、简单工厂模式缺点
三、总结
一、前言
简单工厂模式不属于GoF23种设计模式之一,但是实际中用途广泛,并且可以作为学习“工厂方法模式”以及“抽象工厂模式”的基础。在简单工厂模式中,工厂类提供一个创建产品的工厂方法,用于创建各种产品。客户端只需传入对应的参数,利用该方法即可根据传入参数的不同返回不同的具体产品对象。
二、简单工厂模式
简单工厂模式(Simple Factory Pattern):定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。
因为在简单工厂模式用于创建实例的方法是静态的方法,因此简单工厂模式又被称为静态工厂方法模式,它属于类创建型模式。
在介绍简单工厂之前先来看一个简单的计算器小栗子。
1、计算器例子
public static void main(String[] args) {Scanner scanner = new Scanner(System.in);System.out.println("请输入数字A:");String A = scanner.nextLine();System.out.println("请选择运算符号(+、-、*、/):");String B = scanner.nextLine();System.out.println("请输入数字B:");String C = scanner.nextLine();String D = "";if(B == "+"){D = String.valueOf(Double.parseDouble(A) + Double.parseDouble(C));}if(B == "-"){D = String.valueOf(Double.parseDouble(A) - Double.parseDouble(C));}if(B == "*"){D = String.valueOf(Double.parseDouble(A) * Double.parseDouble(C));}if(B == "/"){D = String.valueOf(Double.parseDouble(A) / Double.parseDouble(C));}System.out.println("运算结果:"+D);
}
这段代码存在的问题:
- 这样命名是非常不规范的。像A、B、C、D这些,别人扎眼一看肯定不知道这是在做什么。
- 判断分支,这样的写法,意味着每个条件都要做判断,等于计算机做了三次无用功。
- 如果除数时,客户输入了0怎么办,如果用户输入的是字符符号而不是数字怎么办。
2、优化后版本
public static void main(String[] args) {try {Scanner scanner = new Scanner(System.in);System.out.println("请输入数字A:");String numberA = scanner.nextLine();System.out.println("请选择运算符号(+、-、*、/):");String operate = scanner.nextLine();System.out.println("请输入数字B:");String numberB = scanner.nextLine();String result = "";switch (operate ){case "+":result = String.valueOf(Double.parseDouble(numberA) + Double.parseDouble(numberB));break;case "-":result = String.valueOf(Double.parseDouble(numberA) - Double.parseDouble(numberB));break;case "*":result = String.valueOf(Double.parseDouble(numberA) * Double.parseDouble(numberB));break;case"/":if (numberB != "0"){result = String.valueOf(Double.parseDouble(numberA) / Double.parseDouble(numberB));}else{result = "除数不能为0";}break;}System.out.println("运算结果:"+result);}catch (Exception e){System.out.println(e);}}
可以看到这一版中优化了变量的命名,将if判断更换成了switch case语句,增加了除数判断是否为0。
3、结合面向对象进行优化(封装)
3.1、Operation运算类
public class Operation {public static String getResult(double numberA, double numberB, String operate){String result = "";switch (operate){case "+":result = String.valueOf(numberA+ numberB);break;case "-":result = String.valueOf(numberA -numberB);break;case "*":result = String.valueOf(numberA * numberB);break;case"/":if (numberB != 0){result = String.valueOf(numberA / numberB);}else{result = "除数不能为0";}break;}return result;}
}
3.2、客户端
public class Program {public static void main(String[] args) {try {Scanner scanner = new Scanner(System.in);System.out.println("请输入数字A:");String numberA = scanner.nextLine();System.out.println("请选择运算符号(+、-、*、/):");String operate = scanner.nextLine();System.out.println("请输入数字B:");String numberB = scanner.nextLine();String result = "";Operation.getResult(Double.parseDouble(numberA), Double.parseDouble(numberB),operate);System.out.println("运算结果:"+result);}catch (Exception e){System.out.println(e);}}
}
4、利用面向对象三大特性(继承和多态)
4.1、Operation类
public abstract class Operation {private double numberA;private double numberB;public double getNumberA() {return numberA;}public void setNumberA(double numberA) {this.numberA = numberA;}public double getNumberB() {return numberB;}public void setNumberB(double numberB) {this.numberB = numberB;}public abstract double getResult() throws Exception;
}
4.2、加法类
public class OperationAdd extends Operation{@Overridepublic double getResult() {return getNumberA()+getNumberB();}
}
4.3、减法类
public class OperationSub extends Operation{@Overridepublic double getResult() {return getNumberB() - getNumberB();}
}
4.4、乘法类
public class OperationMul extends Operation{@Overridepublic double getResult() {return getNumberA() * getNumberB();}
}
4.5、除法类
public class OperationDiv extends Operation{@Overridepublic double getResult() throws Exception {if (getNumberB() != 0){return getNumberA() / getNumberB();}throw new Exception("除数不能为0");}
}
4.6、简单工厂
public class OperationFactory {public static Operation createOperate(String operate){Operation operation = null;switch (operate){case "+":operation = new OperationAdd();break;case "-":operation = new OperationSub();break;case "*":operation = new OperationMul();break;case"/":operation = new OperationDiv();break;}return operation;}
}
4.7、客户端
public class Program {public static void main(String[] args) throws Exception {Operation operation;operation = OperationFactory.createOperate("+");operation.setNumberA(2);operation.setNumberB(4);double result = operation.getResult();System.out.println(result);}
}
5、简单工厂模式优点
1、工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品;简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象。
2、客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者的记忆量。
3、通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。
6、简单工厂模式缺点
1、由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。
2、使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。
3、系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
4、简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。
三、总结
使用了简单工厂之后,如果有一天我们需要更改假发运算,只需要更改OperationAdd就可以了,如果需要增加各种复杂运算,例如:平方根、自然对数、正弦等,需要增加相应的运算子类,修改运算类工厂,在switch中增加分支,来看一下简单工厂的类结构。
相关文章:

设计模式—简单工厂
目录 一、前言 二、简单工厂模式 1、计算器例子 2、优化后版本 3、结合面向对象进行优化(封装) 3.1、Operation运算类 3.2、客户端 4、利用面向对象三大特性(继承和多态) 4.1、Operation类 4.2、加法类 4.3、减法类 4…...

真机安装Linux Centos7
准备工具: 8G左右U盘最新版UltraISOCentOS7光盘镜像 操作步骤 下载镜像 地址:http://isoredirect.centos.org/centos/7/isos/x86_64/ 安装刻录工具UltraISO,刻录镜像到U盘 ① 选择ISO镜像文件 ② 写入磁盘镜像,在这里选择你的U盘…...

ceph peering机制-状态机
本章介绍ceph中比较复杂的模块: Peering机制。该过程保障PG内各个副本之间数据的一致性,并实现PG的各种状态的维护和转换。本章首先介绍boost库的statechart状态机基本知识,Ceph使用它来管理PG的状态转换。其次介绍PG的创建过程以及相应的状…...
Java | File类
目录: File类File类中常用的方法:boolean exists( ) :判断此 文件/目录 是否存在boolean createNewFile( ) :创建一个文件boolean mkdir( ) :创建 “单层” 目录/文件夹boolean mkdirs( ) :创建 “多层” 目…...
数学建模之灰色预测
灰色预测(Grey Forecasting)是一种用于时间序列数据分析和预测的方法,通常用于处理具有较少历史数据的情况或者数据不够充分的情况。它是一种非常简单但有效的方法,基于灰色系统理论,用来估计未来的趋势。 以下是灰色…...
03_nodejd_npm install报错
npm install报错 npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree npm ERR! npm ERR! While resolving: 5kcrm11.0.0 npm ERR! Found: vue2.5.17 npm ERR! node_modules/vue npm ERR! vue"2.5.17" from the root project npm ERR! np…...

three.js(二):webpack + three.js + ts
用webpackts 开发 three.js 项目 webpack 依旧是主流的模块打包工具;ts和three.js 是绝配,three.js本身就是用ts写的,ts可以为three 项目提前做好规则约束,使项目的开发更加顺畅。 1.创建一个目录,初始化 npm mkdir demo cd de…...

最小二乘法处理线性回归
最小二乘法是一种数学优化技术,用于查找最适合一组数据点的函数。 该方法主要用于线性回归分析,当然,也可用于非线性问题。 开始之前,我们先理解一下什么是回归。 回归:回归是一种监督学习算法,用于建模和…...
ModbusCRC16校验 示例代码
作者: Herman Ye Galbot Auromix 测试环境: Ubuntu20.04 更新日期: 2023/08/30 注1: Auromix 是一个机器人爱好者开源组织。 注2: 本文在更新日期经过测试,确认有效。 笔者出于学习交流目的, 给…...

一不留神就掉坑
乘除顺序问题 在据卡特兰数[1]公式,解决leetcode-96 不同的二叉搜索树[2]时,遇到一个非常诡异的问题, package mainimport "fmt"func main() { for i : 0; i < 40; i { fmt.Printf("第%d个卡特兰数为:%d\n", i, numTrees(i)) }}func numTrees(n int) i…...

Redis数据类型(list\set\zset)
"maybe its why" List类型 列表类型是⽤来存储多个有序的字符串,列表中的每个字符串称为元素(element),⼀个列表最多可以存储个2^32 - 1个元素。在Redis中,可以对列表两端插⼊(push)…...
TongWeb安装以及集成
TongWeb 安装步骤 静默安装 获取linux可执行安装包 如: Install_TWx.x.x.x_Enterprise_Linux.bin 创建安装所需配置文件 install.properties 内容如下 [root@node5 tongweb]# cat install.properties INSTALL_UI=silent USER_INSTALL_DIR=/home/tongweb SILENT_JDK_HOME=/jd…...

ScreenToGif-动图制作软件实用操作
ScreenToGif官网:ScreenToGif ⭕第一步:启动页面 ⭕第二步:选项 🥝录像机-捕获频率选择手动-播放延迟1000ms(可以任意) ⭕第三步:录像机开始录屏 🥝我们调整录屏的大小后,打开画图,…...

sqlibs安装及复现
sqlibs安装 安装phpstudy后,到github上获取sqlibs源码 sqli-labs项目地址—Github获取:GitHub - Audi-1/sqli-labs: SQLI labs to test error based, Blind boolean based, Time based. 在phpstudy本地文件中的Apache目录中解压上方下载的源码。 将sq…...
OpenAI 创始人 Sam Altman 博客有一篇 10 年前的文章
OpenAI 创始人 Sam Altman 博客有一篇 10 年前的文章《Advice for ambitious 19 year olds》,给 19 岁年轻人的建议,从 #参考答案 看到,非常适合我们🤣年轻人,顺便用 GPT4 重新翻译了下全文。 太长不读纯摘要版本如下&…...

写的一款简易的热点词汇记录工具
项目需要对用户提交的附件、文章、搜索框内容等做热词分析。如下图: 公司有大数据团队。本着不麻烦别人就不麻烦别人的原则,写了一款简易的记录工具,原理也简单,手工在业务插入锚点,用分词器分好词,排掉字…...

算法通关村——滑动窗口高频问题
1. 无重复字符的最长子串 给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: s “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。 1.1 滑动窗口 找到最长字串需要找到字串的首尾位置…...

mybatis源码学习-2-项目结构
写在前面,这里会有很多借鉴的内容,有以下三个原因 本博客只是作为本人学习记录并用以分享,并不是专业的技术型博客笔者是位刚刚开始尝试阅读源码的人,对源码的阅读流程乃至整体架构并不熟悉,观看他人博客可以帮助我快速入门如果只是笔者自己观看,难免会有很多弄不懂乃至理解错误…...

selenium 自动化测试——环境搭建
安装python,并且使用pip命令安装 selenium pip3 install selenium 然后尝试第一次使用selenium 完成一个简单的测试自动化脚本 from selenium import webdriver from selenium.webdriver.common.by import By import timedriver webdriver.Chrome() driver.get(…...

得物一面,场景题问得有点多!
题目来源:https://www.nowcoder.com/discuss/525371909735792640 前文 本期是【捞捞面经】系列文章的第 1 期,持续更新中…。 《捞捞面经》系列正式开始连载啦,据说看了这个系列的朋友都拿到了大厂offer~ 欢迎星标订阅,持续更新…...

第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...

使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...

push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...