【设计模式】简单工厂模式——以一个简单的计算器为例
2015-12-04 13:51
836 查看
本文内容参考自《大话设计模式》(程杰 著)
注:以下代码为C#实现
毛病:命名不规范,判断分支做多次无用功,除数为0时出错,输入不是数字……
以上代码规范了,但是可重用性差!
客户端代码
问题:如果我要增加其他运算,或者是想要修改运算的法则,那么其他代码都会受到影响,比如要重新编译,调试等等。
加减乘除类
在这里,我们定义了一个虚函数,然后其他运算继承操作类并实现该函数,这样子,如果要增加其他运算,只需要增加一个类来继承操作类就可以了,而且单个操作的修改完全不影响其他的运算!
使用简单的工厂模式可以避免这个问题:
简单运算工厂类
客户端代码
如果一来,客户端就简化了很多,它只需要知道 OperationFactory,并通过createOperate传入相应的操作就可以了!
当我们需要修改加法运算时,只需要修改OperationAdd,当我们需要增加其他运算时,只需要增加相应的运算子类,并在运算类工厂中增加分支即可。
同时,界面显示和我们的业务逻辑也是分离的~
UML图:
注:以下代码为C#实现
1.拙劣的代码
class Program { static void Main(string[] args) { Console.Write("请输入数字A:"); string A = Console.ReadLine(); Console.Write("请选择运算符号(+、-、*、/):"); string B = Console.ReadLine(); Console.Write("请输入数字B:"); string C = Console.ReadLine(); string D = ""; if (B == "+") D = Convert.ToString(Convert.ToDouble(A) + Convert.ToDouble(C)); if (B == "-") D = Convert.ToString(Convert.ToDouble(A) - Convert.ToDouble(C)); if (B == "*") D = Convert.ToString(Convert.ToDouble(A) * Convert.ToDouble(C)); if (O == "/") D = Convert.ToString(Convert.ToDouble(A) / Convert.ToDouble(C)); Console.WriteLine("结果是:" + D); } }
毛病:命名不规范,判断分支做多次无用功,除数为0时出错,输入不是数字……
2.规范化
class Program { 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 = ""; switch (strOperate) { case "+": strResult = Convert.ToString(Convert.ToDouble(strNumberA) + Convert.ToDouble(strNumberB)); break; case "-": strResult = Convert.ToString(Convert.ToDouble(strNumberA) - Convert.ToDouble(strNumberB)); break; case "*": strResult = Convert.ToString(Convert.ToDouble(strNumberA) * Convert.ToDouble(strNumberB)); break; case "/": if (strNumberB != "0") strResult = Convert.ToString(Convert.ToDouble(strNumberA) / Convert.ToDouble(strNumberB)); else strResult = "除数不能为0"; break; } Console.WriteLine("结果是:" + strResult); Console.ReadLine(); } catch (Exception ex) { Console.WriteLine("您的输入有错:" + ex.Message); } } }
以上代码规范了,但是可重用性差!
3.业务的封装
Operation运算类public class Operation { public static double GetResult(double numberA, double numberB, string operate) { double result = 0d; switch (operate) { case "+": result = numberA + numberB; break; case "-": result = numberA - numberB; break; case "*": result = numberA * numberB; break; case "/": result = numberA / numberB; break; } return result; } }
客户端代码
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); } }
问题:如果我要增加其他运算,或者是想要修改运算的法则,那么其他代码都会受到影响,比如要重新编译,调试等等。
4.松耦合
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; } }
加减乘除类
class OperationAdd : Operation { public override double GetResult() { double result = 0; result = NumberA + NumberB; return result; } } class OperationSub : Operation { public override double GetResult() { double result = 0; result = NumberA - NumberB; return result; } } class OperationMul : Operation { public override double GetResult() { double result = 0; result = NumberA * NumberB; return result; } } class OperationDiv : Operation { public override double GetResult() { double result = 0; if (NumberB==0) throw new Exception("除数不能为0。"); result = NumberA / NumberB; return result; } }
在这里,我们定义了一个虚函数,然后其他运算继承操作类并实现该函数,这样子,如果要增加其他运算,只需要增加一个类来继承操作类就可以了,而且单个操作的修改完全不影响其他的运算!
5.简单工厂模式
使用上面代码之后,我们在客户端需要实例化相应的类,比如‘+’操作需要实例化OperationAdd,减操作需要实例化OperationSub,这样子暴露给客户的信息太多了,客户必须知道每个操作它对应的类!使用简单的工厂模式可以避免这个问题:
简单运算工厂类
public class OperationFactory { public static Operation createOperate(string operate) { Operation oper = null; switch (operate) { case "+": oper = new OperationAdd(); break; case "-": oper = new OperationSub(); break; case "*": oper = new OperationMul(); break; case "/": oper = new OperationDiv(); break; } return oper; } }
客户端代码
Operation oper; oper = OperationFactory.createOperate(“+”); oper.NumberA = 1; oper.NumberB = 2; double result = oper.GetResult();
如果一来,客户端就简化了很多,它只需要知道 OperationFactory,并通过createOperate传入相应的操作就可以了!
当我们需要修改加法运算时,只需要修改OperationAdd,当我们需要增加其他运算时,只需要增加相应的运算子类,并在运算类工厂中增加分支即可。
同时,界面显示和我们的业务逻辑也是分离的~
UML图:
相关文章推荐
- Android Service生命周期 Service里面的onStartCommand()方法详解
- android典型代码系列(三)------数据库URI收集
- Android中常用的位图操作(View与Bitmap转化、圆角、灰化、提取Alpha、旋转、倒影、剪切……)
- 关于开发中 hosts 文件的修改
- CF div2 334 C
- 阿里云的esc
- 丢失的数字
- 1.iOS开发系列--C语言之基础知识
- 深入理解C First
- 欧拉函数求法与欧拉筛法求素数
- Unity中的自定义鼠标
- 查看gcc预定义的宏
- 交互还有事件触发。
- scala 元组tuple的几个知识点-提供分
- android典型代码系列(二)------sqlite数据库操作高级
- 从源码中分析Hadoop的RPC机制
- GoldGate 配置学习笔记
- MyBatis学习笔记(三)数据的增删改查 CRUD操作
- 欧拉函数求法与欧拉筛法求素数
- SoundPool