前言

最近在拜读《大话设计模式》这本书,作为一个小白中的小白,读完以后感触还是很深的。再次做一个学习的记录,同时也算给自己多一次实践的机会。

问题

相信大家在上学时都写过“简易计算器”,就是要求很简单的键盘输入两个数字,然后再给定一个符号,去做加减乘除运算。最简单的计算器实现,实在是大学老师最爱的练习小demo之一呢hhhh

V1.0版本

大家思路都差不多,这不是直接一个switch就解决了吗?这不是有手就行?立马感觉自己能进BAT了呢hhhh(瞎掰的)

public static void main(String[] args) {//假装这是用户输入的东西Double num = null;Double otherNum = null;String operator = "*";Double result = null;//使用switch进行比对switch (operator){case "+":result = num+otherNum;break;case "-":result = num-otherNum;break;case "*":result = num*otherNum;break;case "/"://判断被除数不能为0if (otherNum != 0){result = num/otherNum; }break;}}

这样写就存在两个问题。

1.如果用户输出的是"/",那么前三次对比就相当于做了无用功,虽然在这种微乎其微的程序上没影响,但是一旦数量多了起来那就难以想象了。

2.从面向对象的设计原则上说,其实有违开闭原则。

开闭原则:对扩展开放,对修改封闭

以上述例子来说就是,允许增加新的计算方式,比如增加取余运算。但是原则上不允许修改原有的计算方式(加减乘除)!当然也不会有人有病去瞎改hhh,但是指不定手滑呢,就可能会导致原有的代码运行出问题。

于是2.0版本就应运而生!

V2.0版本

脑子一转,那可以考虑工具类。将业务逻辑部分进行封装。这样就遵循开闭原则了吧,至少是部分遵守了hhhh

public class OperationUtils {public static Double GetResult(double num,double otherNum,String operator){Double result = null;switch (operator){case "+":result = num+otherNum;break;case "-":result = num-otherNum;break;case "*":result = num*otherNum;break;case "/"://判断被除数不能为0if (otherNum != 0){result = num/otherNum;}break;}return result;}
}

但是这也只是仅仅达到了封装的目的,如果按照我们以上的设想,当我们需要增加运算方式时,其实还是要去修改工具类里的东西,所以根本上还是没有遵守开闭原则。

于是v3.0版本应运而生..........

V3.0版本

首先设计一个计算的接口,其中只有一个得到计算结果的方法。至于如何实现,就根据不同实现类的计算方式即可。

计算操作接口

public interface Operation {/*** 计算结果的方法* @param num* @param otherNum* @return*/Double getResult(double num,double otherNum);
}

加法实现类

/*** 加法实现类*/
public class AddOperation implements Operation{//重写加法的计算方法@Overridepublic Double getResult(double num, double otherNum) {Double result = null;result = num + otherNum;return result;}
}

减法实现类

/*** 减法实现类*/
public class SubOperation implements Operation {//重写减法的计算方法@Overridepublic Double getResult(double num, double otherNum) {Double result = null;result = num - otherNum;return result;}
}

剩余的实现类相信各位大佬肯定知道咋写了吧,这里本人就不一一展示了,就当给各位练练手吧(有懒狗,我不说是谁)

主函数

 public static void main(String[] args) {//假装这是用户输入的东西Double num = null;Double otherNum = null;String operator = "*";Double result = null;//加法实现AddOperation addOperation = new AddOperation();result = addOperation.getResult(num,otherNum);//减法实现SubOperation subOperation = new SubOperation();result = subOperation.getResult(num,otherNum);
}

至此,看起来就比较符合开闭原则了。

如果还需要增加计算方式,只需要实现计算方法接口即可。在增加时,因为根本不是同一个实现类,也就不要担心手滑碰到原有的代码从而导致被老板开除hhhh。

扩展知识点:面向接口编程

这也就是大家常说的面向接口编程,可以通俗理解为只将方法暴露在外,实际实现的逻辑其实在不同的实现类中。面向接口编程最早的体现(针对我来说)——为啥在三层架构中,业务逻辑层为啥要弄个Interface,然后又要搞个实现类去重写方法。这不是脱裤子放屁吗?我直接写我需要的方法不就好了。

现在想想当初的自己还是天真了hhhh,不得不感叹面向对象的博大精深啊...

策略模式

另外诸如此类的实现方法,也体现了设计模式的策略模式。

通俗理解:将不同的算法(加法,减法,乘法,除法)进行封装,这就可以让不同的地方使用相同的算法。也就是我那一天心血来潮新写了计算器plus,我就不用再把加减乘除的方法重新写一遍,直接把之前封装好的拿过来用就好了。(这样也避免了大量分支判断的存在,导致整个代码显得非常臃肿并且后期难以维护和修改)

因为本小弟也是初学者,理解得可能不是很透彻,有兴趣的hxd往这走

有趣的设计模式——解救抓狂的商场收银员

V4.0版本

以为3.0就完结了?必定不可能!其实在计算方面确实做的差不多了(以我的能力而言),4.0更多的是针对现有代码基础的优化。

我们虽然写了不同的计算实现类,但是在每次需要使用的时候,都要new一个对应实现类的对象,然后再调用getResult()方法进行计算。这样计算的东西少一点还好,要是用户加减乘除挨个来一遍,再倒着来一遍,那岂不是new对象都要花费很多时间???

简单工厂模式

通俗理解:我们需要一个各种实现类的集中制造基地,我们只要告诉工厂我要加法或者减法,它就直接给我们即可,不需要我们繁琐的自己去new一个新的对象。

简单计算实现类工厂

public class OperationFactory {/*** 获取实现类对象方法* @param operator* @return*/public static Operation createOperation(String operator){Operation operation = null;//看运算符来判断需要生成的实现类switch (operator){case "+":operation = new AddOperation();break;case "-":operation = new SubOperation();break;case "*":operation = new MultiplicaOperation();break;case "/":operation = new DivOperation();break;}return operation;}
}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------更新于2022.09.26----------------------------------------------------------

简单工厂模式PRO

最近看到一个新的写法,就此记录下。首先我们分析下现有的简单工厂,主要存在两个问题。

1.代码入侵性比较强,每次在添加新的“计算方法”的时候,都要在OperationFactory类中进行新增,其实是有违开闭原则的。

2.多分支的判断,导致做了很多无用功。比如说:当前需要除法,但是必须case到最后一个分支才能得到,也就是前三次对比其实是无用功。

那么我们考虑通过反射来进行代码的优化

思路:通过反射直接进行对象的实例化

创建一个相关配置文件,后期更加方便修改。其中存对应的包名。

更改简单工厂类

public class OperationFactory {public static Operation createOperation(String name){//首先读取配置文件,获取对应包名Properties properties = new Properties();Class<?> cls = null;Operation operation = null;try {//读取配置文件properties.load(new FileInputStream("src/main/resources/name.properties"));//获取包名String className = properties.getProperty(name);//通过反射实例化对象cls = Class.forName(className);operation = (Operation) cls.newInstance();}catch (Exception e){System.out.println("处理异常...");}return operation;}
}

测试类

public class Test {public static void main(String[] args) {//假装这是用户输入的东西Double num = 10.5;Double otherNum = 2.5;Double result = null;//加法实现Operation addOperation = OperationFactory.createOperation("Add");result = addOperation.getResult(num,otherNum);System.out.println("加法计算结果:"+result);//减法实现Operation subOperation = OperationFactory.createOperation("Sub");result = subOperation.getResult(num,otherNum);System.out.println("减法计算结果:"+result);}
}

结果展示

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------更新于2022.09.27-----------------------------------------------------

工厂方法模式

昨天的我无法理解工厂方法模式,今天的我突然茅塞顿开,再次记录一下。

何为工厂方法模式?和简单工厂的区别是什么?

工厂方法模式是对简单工厂的再一次抽象,克服了简单工厂的一些缺点。

举个栗子来说

=========================================================================

简单工厂模式:一个手机工厂同时造安卓手机(对象)和水果手机(对象)

工厂方法模式:手机工厂分为安卓手机厂(工厂)和水果手机厂(工厂),安卓手机厂只造安卓手机,水果厂只造水果手机

=========================================================================

书接上文,直接上代码。

1.首先准备一个公共工厂接口,需要实现创建实例的方法

public interface Factory {Operation createOperation();
}

2.加法工厂的实现,通过实现工厂接口从而重写方法

public class AddOperationFactory implements Factory{@Overridepublic Operation createOperation() {AddOperation addOperation = new AddOperation();return addOperation;}
}

减法工厂,乘法工厂,除法工厂以此类推,就不(有)演(懒)示(狗)了。

小结(简单工厂和工厂方法的区别)

1.简单工厂其实是违背开闭原则的,因为每次新增创建实例的判断,其实都需要在原来的地方进行修改。而工厂方法只是实现接口,也就是不会修改原有的代码,只是做新增。

2.简单工厂将创建什么的实例(加法还是减法)的逻辑判断放在了内部,而工厂方法其实把这个判断移到了客户端进行,只有在创建时由客户端进行判断。

示例:

简单工厂测试类

public class Test {public static void main(String[] args) {//假装这是用户输入的东西Double num = 10.5;Double otherNum = 2.5;Double result = null;//加法实现//用户只负责讲运算符传入,具体实例哪个对象在内部进行判断Operation addOperation = OperationFactory.createOperation("Add");result = addOperation.getResult(num,otherNum);System.out.println("加法计算结果:"+result);}
}

工厂方法测试类

public class Test {public static void main(String[] args) {//假装这是用户输入的东西Double num = 10.5;Double otherNum = 2.5;Double result = null;//在客户端时,就知道需要创建的是加法工厂,而不是在内部进行判断Factory factory = new AddOperationFactory();Operation addOperation = factory.createOperation();result = addOperation.getResult(num,otherNum);}
}

工厂方法模式后续优化同样可以考虑由反射进行实例创建,这里留个坑过后补上。

任何设计模式没有绝对的好与坏,只看那种情况下的适配性最好,什么时候是最佳选择!

总结

至此真的完结了,仅仅看了第一小节,感觉腰不疼了,腿不酸了呢,实乃上古神书之一!

以上纯属瞎掰。

分享书中一句话:编程是一门技术,更是一门艺术。

曾经我就很好奇,大家都是流水线式的逻辑进行业务的实现,这还能分出好坏?现在看来实在是当初自己太年轻了hhh。

如有问题,请各位大佬指正。-----记一个菜狗的学习记录

从简易计算器到设计模式(策略、简单工厂)相关推荐

  1. java 工厂模式 计算器_java设计模式之简单工厂模式

    在编写一个计算器程序时,可以将业务逻辑和显示分离,业务逻辑封装为一个类(封装):如果要新添加一种运算,可以先创建一个Operation的基类,然后各种运算从Operation类继承,并实现GetRes ...

  2. php的类图怎么生成_PHP设计模式之简单工厂模式

    PHP设计模式之简单工厂模式 先从简单工厂入门,不管是面试还是被他人面试,在问到设计模式的时候,大多数人都会提到工厂模式.毫无疑问,工厂相关的几种模式在设计模式中是最出名的也是应用比较广泛的一种模式. ...

  3. C#设计模式(2)——简单工厂模式

    一.引言 这个系列也是自己对设计模式的一些学习笔记,希望对一些初学设计模式的人有所帮助的,在上一个专题中介绍了单例模式,在这个专题中继续为大家介绍一个比较容易理解的模式--简单工厂模式. 二.简单工厂 ...

  4. 工厂模式 java场景_研磨设计模式之简单工厂模式(场景问题)

    简单工厂不是一个标准的设计模式,但是它实在是太常用了,简单而又神奇,所以还是需要好好掌握的,就当是对学习设计模式的热身运动吧.为了保持一致性,我们尽量按照学习其它模式的步骤来进行学习. 1  场景问题 ...

  5. .NET设计模式(1): 简单工厂模式

    .NET设计模式(1): 简单工厂模式 最近一直在看设计模式,想把自己的学习笔记与大家分享一下,如果能帮助大家的话,我会非常高兴,同时也欢迎大家指出里面的不足.园子里其实关于此类文章已经很多了,如果d ...

  6. JS常用的设计模式(2)——简单工厂模式

    JS常用的设计模式(2)--简单工厂模式 简单工厂模式是由一个方法来决定到底要创建哪个类的实例, 而这些实例经常都拥有相同的接口. 这种模式主要用在所实例化的类型在编译期并不能确定, 而是在执行期决定 ...

  7. 设计模式之简单工厂模式(C#版)

    设计模式之简单工厂模式(C#版) 简介 假设有个女朋友 总结 简介 我用最简洁而直接的方式来描述一下,什么是简单工厂模式.一句话就是,工厂类使用switch case语句返回特定类型. 下面,我们用一 ...

  8. 大牧絮叨设计模式:简单工厂模式

    文章目录 1. 简单工厂模式概述 1.1.简单工厂模式核心组件 1.2.简单工厂模式优缺点 2.` Java`实现 公共父类定义 产品具体实现类 简单工厂定义 代码运行测试: 3. `Python`实 ...

  9. 设计模式之简单工厂模式(Java 实现)

    设计模式之简单工厂模式(Java 实现) 本文首发于http://www.imooc.com/wiki/Designlesson/factory.html 简单工厂模式是平时开发过程中最常见的设计模式 ...

  10. 工厂设计模式、简单工厂设计模式、抽象工厂设计模式

    一.简单工厂设计模式.工厂设计模式,抽象工厂设计模式总体分析 简单工厂模式 简单工厂模式不是23种里的一种,简而言之,就是有一个专门生产某个产品的类. 比如下图中的鼠标工厂,专业生产鼠标,给参数0,生 ...

最新文章

  1. Dockerfile文件命令详解
  2. 开发日记-20190516 关键词 MVVM-代码浏览结束
  3. Darwin Stream server(DSS服务器)的Relay(中继/转发)设置
  4. created写法_在vue中created、mounted等方法使用小结
  5. 批量清除为Button注册的事件
  6. Extjs4 MVC 添加view层
  7. java中的多态与继承_【Java学习笔记之十六】浅谈Java中的继承与多态
  8. 为什么Mac source ~/.bash_profile只生效一次(macOS Catalina)
  9. 勤哲excel服务器WEB网页环境搭建问题解决
  10. python写病毒代码_手把手教你!100行代码,用Python做一个“消灭病毒”的小游戏...
  11. ActivityMQ 事务
  12. matlab随机生成点图,matlab随机生成散点图
  13. oppo enco free2 固件降级工具 (仅供测试使用)
  14. Ubuntu 更改环境变量 PATH
  15. cogs——2098. Asm.Def的病毒
  16. Stepping Number
  17. 思科交换机接口安全配置
  18. c#操作excel方式三:使用Microsoft.Office.Interop.Excel.dll读取Excel文件
  19. 查询最近三个月的数据
  20. ALV中的回车事件相应及添加F4帮助

热门文章

  1. 仿写微信公众号添加自定义菜单 并给后台存数据
  2. Unity使用Newtonsoft.Json插件实现XML与JSON数据的互转
  3. 利用CC2530单片机的蜂鸣器播放音乐的代码
  4. 判断三角形(PTA厦大慕课)
  5. 常用H5标签-第三部分
  6. js通过class获取元素
  7. 报表生成器FastReport .Net注册数据教程
  8. Apache Calcite教程-SQL解析-Calcite SQL解析
  9. H.264编码技术(zz)
  10. HDMI光纤线,英文称呼:hdmi AOC Cable,又被称为有源光缆。