[设计模式学习]设计模式学习之简单工厂模式
2015-08-12 17:06
302 查看
最近在看《大话设计模式》,就做了一些学习笔记。
当然语言不是问题,本文采用C#语言。
面试单位要求用任意一种面向对象语言的面向对象思想实现一个计算机控制台程序,要求输入两个数和运算符号,得到结果。
第一次写的代码如下:
乍一看,功能实现了,其实有很多不足之处。
1、A,B,C,D这样的命名极不规范。
2、if的判断分支,意味着每个条件都要做判断,等于计算机做了三次无用功。
3、如果除数时,用户输出了0怎么办?如果用户输入的是字符符号而不是数字怎么办?
马上改,第二次修改代码如下:
大功告成了?别忘了出题人说的是面向对象,这里没有面向对象的思想。我们碰到问题总是直觉的用计算机能够理解的逻辑思维来描述和表达解决的问题及具体的求解过程。这样的思维使得我们的程序使得我们的程序只为满足实现当前的需求,程序不容易维护,不容易扩展,更不容易复用。从而达不到高质量代码的要求。
我们可以考虑通过封装,继承,多态把程序的耦合度降低。如果公司要求你再写一个Windows的计算器,如何复用代码呢?最好是让业务逻辑和界面逻辑分开,让他们之间的耦合度降低。
Operator运算类
客户端代码:
有了面向对象的思想了吗?面向对象有三大特性:封装,继承,多态,这里只用到了封装,继续改。
Operation运算类:
加减乘除类:
现在的问题是如何去实例化对象。好了,重点来了。”简单工厂模式”告诉你到底要实例化谁,将来会不会增加实例化的对象,我们应该考虑用单独的一个类来做这个创造实例的过程,这就是工厂。
简单运算工厂类:
客户端代码:
现在不关你是控制台程序,Windows程序,Web程序,PDA或手机程序,都可以采用这段代码来实现计算机的功能,如果有一天我们需要更改加法运算,只需要更改OperationAdd。如果需要增加各种复杂运算,只要增加相应的运算子类然后修改运算类工厂,在switch中添加分支就可以了,如果需要修改界面,直接修改就可以不需要修改运算。
心得:编程是一门技术,更是一项艺术。我们不能只满足于运行结果正确。时常考虑让代码更加简练,更加容易维护,容易扩展和复用,这样才不叫“搬砖”,才能得到真正提高。
当然语言不是问题,本文采用C#语言。
面试单位要求用任意一种面向对象语言的面向对象思想实现一个计算机控制台程序,要求输入两个数和运算符号,得到结果。
第一次写的代码如下:
class Program { static void Main(String[] args) { Console.WriteLine("请输入数字A:"); string A = Console.ReadLine(); Console.WriteLine("请选择运算符号(+,-,*,/):"); 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(B == "/") { D = Convert.ToString(Convert.ToDouble(A) / Convert.ToDouble(C)); } Console.WriteLine("结果是:" + D); } }
乍一看,功能实现了,其实有很多不足之处。
1、A,B,C,D这样的命名极不规范。
2、if的判断分支,意味着每个条件都要做判断,等于计算机做了三次无用功。
3、如果除数时,用户输出了0怎么办?如果用户输入的是字符符号而不是数字怎么办?
马上改,第二次修改代码如下:
class Program { static void Main(String[] args) { try { Console.WriteLine("请输入数字A:"); string strNumberA = Console.ReadLine(); Console.WriteLine("请选择运算符号(+,-,*,/):"); 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); } } }
大功告成了?别忘了出题人说的是面向对象,这里没有面向对象的思想。我们碰到问题总是直觉的用计算机能够理解的逻辑思维来描述和表达解决的问题及具体的求解过程。这样的思维使得我们的程序使得我们的程序只为满足实现当前的需求,程序不容易维护,不容易扩展,更不容易复用。从而达不到高质量代码的要求。
我们可以考虑通过封装,继承,多态把程序的耦合度降低。如果公司要求你再写一个Windows的计算器,如何复用代码呢?最好是让业务逻辑和界面逻辑分开,让他们之间的耦合度降低。
Operator运算类
public class Operation { public static double GetResult(double numberA, double numberB, string operator) { double result = 0d; switch(operator) { 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.WriteLine("请输入数字A:"); string strNumberA = Console.ReadLine(); Console.WriteLine("请选择运算符号(+,-,*,/):"); string strOperate = Console.ReadLine(); Console.Write("请输入数字B:"); string strNumberB = Console.ReadLine(); string strResult = ""; strResult = Convert.ToString(Operation.GetResult(ConvertToDouble(strNumberA), ConvertToDouble(strNumberB), strOperate)); Console.WriteLine("结果是:" + strResult); Console.ReadLine(); } catch(Exception ex) { Console.WriteLine("您的输入有错:" + ex.Message); } }
有了面向对象的思想了吗?面向对象有三大特性:封装,继承,多态,这里只用到了封装,继续改。
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; } }
现在的问题是如何去实例化对象。好了,重点来了。”简单工厂模式”告诉你到底要实例化谁,将来会不会增加实例化的对象,我们应该考虑用单独的一个类来做这个创造实例的过程,这就是工厂。
简单运算工厂类:
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();
现在不关你是控制台程序,Windows程序,Web程序,PDA或手机程序,都可以采用这段代码来实现计算机的功能,如果有一天我们需要更改加法运算,只需要更改OperationAdd。如果需要增加各种复杂运算,只要增加相应的运算子类然后修改运算类工厂,在switch中添加分支就可以了,如果需要修改界面,直接修改就可以不需要修改运算。
心得:编程是一门技术,更是一项艺术。我们不能只满足于运行结果正确。时常考虑让代码更加简练,更加容易维护,容易扩展和复用,这样才不叫“搬砖”,才能得到真正提高。
相关文章推荐
- Spring 中的default-lazy-init="true" 和 lazy-init="true"
- 清除浮动方法及优缺点
- 谁是Windows 10中国市场的赢家?
- Android应用的性能问题
- Java进阶(十二)JDK版本错误之Unsupported major.minor version 51.0(jdk版本错误)
- string和C-风格字符串输入方式详解
- Redis报错:ERR Operation against a key holding the wrong kind of value 解决处理
- zoj1654 Place the Robots
- hdu 3085 Nightmare Ⅱ(双向bfs)
- 点击tableview的头视图按钮来达到收放tableview的列表
- 测试
- Linux Socket编程(不限Linux)
- Mac 技巧
- WebSphere MQ7.5教程——教程 2:将消息发送至远程队列
- POJ 1523--SPF【无向图的所有割点 && 删去该点后bcc的数目】
- 视图控制器---UIViewController介绍
- Java进阶(十二)JDK版本错误之Unsupported major.minor version 51.0(jdk版本错误)
- UDP 收/发 广播包
- svn Server sent unexpected return value (403 Forbidden) in response to CHECKOUT
- 玛丽全开-许愿池