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

设计模式笔记(1)简单工厂模式

最近在看程杰的《大话设计模式》,在这里做一点笔记。

书中主要有两个角色:
小菜:初学者,学生;
大鸟:小菜表哥,大佬。
也按图中的对话形式

01 简单工厂模式

要求:使用c++、Java、C#或VB.NET任意一种面向对象语言实现一个计算器控制台程序,要求输入两个数和运算符号,得到结果。
小菜的代码:
小菜的代码
大鸟指出部分问题:

  1. A, B, C, D 这样的命名不规范;
  2. if的判断分支,逻辑有误,且未考虑除数输入为0/输入为字符非数字等等。

小菜对代码进行修改:
修改后的代码

修改后的逻辑基本没有问题了,但是并没有面向对象。
如何设计出容易维护,容易扩展,又容易复用的计算器程序呢?
程序要避免重复。
小菜:那就是分类,将计算和显示分开?
大鸟:准确说,是让业务逻辑与界面逻辑分开,让它们之间的耦合度下降。只有分离开,才可以达到容易维护或扩展。

接下来,小菜重新进行了尝试:
运算类:
运算类
main函数:

static void Main(string[] args)
{try{Console.Write("请输入数字A:");string strNumberA = Console.ReadLine();Console.Write("请选择运算符号(+、-、*、/):");string strOperate = Console.ReadLine();Console.Write("请输入数字B:");string strNumberB = Console.ReadLine();string strResult = "";strResult = Convert.ToString(Operation.GetResult(Convert.ToDouble(strNumberA),Convert.ToDouble(strNumberB), strOperate));Console.WriteLine("结果是:" + strResult);Console.ReadLine();}catch (Exception ex){Console.WriteLine("您的输入有错:" + ex.Message);}
}​​

目前,无论在windows,还是在web,手机端都可以在需要运算时使用上面运算类的定义。
这里使用到的是“面向对象”的封装。

提问:如何更灵活的修改和扩展代码呢?比如,现在希望增加一个开根号(sqrt)的运算。
小菜:直接修改Operation类?
大鸟:但问题是,要加一个平方根运算,却需要让加减乘除的运算都得来参与编译。而且还可能让原有的运行良好的功能代码产生了变化,这个风险太大了

因此,需要尽量把加减乘除等运算分离,修改其中一个不影响其他
小菜进行新尝试:

operation运算类:

public class Operation
{private double _numberA = 0;private double _numberB = 0;public double NumberA{get  {  return _numberA;  }set  {  _numberA = value;  }}public double NumberB{get  {  return _numberB;  }set  {  _numberB = value;  }}public virtual double GetResult(){double result = 0;return result;}
}​​

两个Number属性,主要用于计算器的前后数,然后有一个虚方法GetResult(),用于得到结果。

加减乘法类:
加减乘法类
加减乘除都写成了运算类的子类,继承它后,重写了GetResult()方法,这样如果要修改任何一个算法,就不需要提供其他算法的代码了。
但是,如何让计算器知道我是希望用哪一个算法呢?

考虑用一个单独的类来做这个创造实例的过程,这就是“工厂”

进行如下设置:
实例化

此时,只需要输入运算符号,工厂就实例化出合适的对象。

一个实例:

Operation oper;
oper = OperationFactory.createOperate(“+”);
oper.NumberA = 1;
oper.NumberB = 2;
double result = oper.GetResult();​​

此时,例如要修改加法运算,改OperationAdd即可。
如果需要增加各种复杂运算,增加相应的运算子类,并在switch中增加分支。

http://www.xdnf.cn/news/15873.html

相关文章:

  • 【图论】图的定义与一些常用术语
  • thinkphp8\guzzlehttp上传文件应用示例
  • Linux基础命令详解:从入门到精通
  • prometheus 黑盒监控和docker检测
  • git操作
  • Node.js:常用工具、GET/POST请求的写法、工具模块
  • ByteBuf 体系的设计与实现
  • `tidyverse` 长表、宽表的处理
  • 【HarmonyOS】ArkUI - 自定义组件和结构重用
  • 处理Electron Builder 创建新进程错误 spawn ENOMEM
  • Spring AI 聊天记忆
  • 28.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--单体转微服务--币种服务(二)
  • Spring Boot 配置文件解析
  • SpringBoot集成MyBatis的SQL拦截器实战
  • Java学习第六十部分——JVM
  • [硬件电路-52]:什么是模拟电路与数字电路;它们的共同点、核心差异点(原理、目标、关注点等)以及它们如何相互转化
  • LeetCode 852:山脉数组的峰顶索引解析与实现
  • STM32CubeMX的一些操作步骤的作用
  • 7-20 关于mysql
  • 网络安全隔离技术解析:从网闸到光闸的进化之路
  • 【硬件】GalaxyTabPro10.1(SM-T520)刷机/TWRP/LineageOS14/安卓7升级小白向保姆教程
  • RxSwift-事件属性
  • JVM-Java
  • LINUX(三)文件I/O、对文件打开、读、写、偏移量
  • 股票及金融笔记
  • 使用Qt6 QML/C++ 和CMake构建海康威视摄像头应用(代码开源)
  • 双8无碳小车“cad【17张】三维图+设计说名书
  • 【橘子分布式】gRPC(编程篇-下)
  • 嵌入式硬件篇---机械臂运动学解算(3自由度)
  • 机器学习-数据预处理