(续上篇)

次日,小菜再来找大鸟,问道:“你昨天说计算器这样的小程序还可以用到面向对象三大特性?继承和多态怎么可能用得上,我实在不可理解。”
        大鸟:“小菜很有钻研精神吗?好,今天我让你功力加深一级。你先要考虑一下,你昨天写的这个代码,能否做到很灵活的可修改和扩展呢?”
        小菜:“我已经把业务和界面分离了呀,这不是很灵活了吗?”
        大鸟:“那我问你,现在如果我希望增加一个开根(sqrt)运算,你如何改?”
        小菜:“那只需要改Operation类就行了,在switch中加一个分支就行了。”
        大鸟:“问题是你要加一个平方根运算,却需要把加减乘除的运算都得来参与编译,如果你一不小心,把加法运算改成了减法,这不是大大的糟糕。打个比方,如果现在公司要求你为公司的薪资管理系统做维护,原来只有技术人员(月薪),市场销售人员(底薪+提成),经理(年薪+股份)三种运算算法,现在要增加兼职工作人员的(时薪)算法,但按照你昨天的程序写法,公司就必须要把包含有的原三种算法的运算类给你,让你修改,你如果心中小算盘一打,‘TMD,公司给我的工资这么低,我真是郁闷,这会有机会了’,于是你除了增加了兼职算法以外,在技术人员(月薪)算法中写了一句

if (员工是小菜)
{salary = salary * 1.1;
}

那就意味着,你的月薪每月都会增加10%(小心被抓去坐牢),本来是让你加一个功能,却使得原有的运行良好的功能代码产生了变化,这个风险太大了。你明白了吗?”

小菜:“哦,你的意思是,我应该把加减乘除等运算分离,修改其中一个不影响另外的几个,增加运算算法也不影响其它代码,是这样吗?”
        大鸟:“自己想去吧,如何用继承和多态,你应该有感觉了。”
        小菜:“OK,我马上去写。”

/// <summary>/// 运算类/// </summary>class Operation{private double _numberA = 0;private double _numberB = 0;/// <summary>/// 数字A/// </summary>public double NumberA{get{ return _numberA; }set{ _numberA = value;}}/// <summary>/// 数字B/// </summary>public double NumberB{get{ return _numberB; }set{ _numberB = value; }}/// <summary>/// 得到运算结果/// </summary>/// <returns></returns>public virtual double GetResult(){double result = 0; return result;}}
 /// <summary>/// 加法类/// </summary>class OperationAdd : Operation{public override double GetResult(){double result = 0; result = NumberA + NumberB;return result;}}/// <summary>/// 减法类/// </summary>class OperationSub : Operation{public override double GetResult(){double result = 0;result = NumberA - NumberB;return result;}}/// <summary>/// 乘法类/// </summary>class OperationMul : Operation{public override double GetResult(){double result = 0;result = NumberA * NumberB;return result;}}/// <summary>/// 除法类/// </summary>class OperationDiv : Operation{public override double GetResult(){double result = 0;if (NumberB==0)throw new Exception("除数不能为0。");result = NumberA / NumberB;return result;}}

小菜:“大鸟哥,我按照你说的方法写出来了一部分,首先是一个运算类,它有两个Number属性,主要用于计算器的前后数,然后有一个虚方法GetResult(),用于得到结果,然后我把加减乘除都写成了运算类的子类,继承它后,重写了GetResult()方法,这样如果要修改任何一个算法,都不需要提供其它算法的代码了。但问题来了,我如何让计算器知道我是希望用哪一个算法呢?”
        大鸟:“写得很不错吗,大大超出我的想象了,你现在的问题其实就是如何去实例化对象的问题,哈,今天心情不错,再教你一招‘简单工厂模式’,也就是说,到底要实例化谁,将来会不会增加实例化的对象(比如增加开根运算),这是很容易变化的地方,应该考虑用一个单独的类来做这个创造实例的过程,这就是工厂,来,我们看看这个类如何写。”

/// <summary>/// 运算类工厂/// </summary>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中增加分支。”
        大鸟: “哈,那才对,那如果要修改界面呢?”
        小菜:“那就去改界面呀,关运算什么事呀。”
        小菜:“ 回想那天我面试题写的代码,我终于明白我为什么写得不成功了,原来一个小小的计算器也可以写出这么精彩的代码,谢谢大鸟。”

(下为当时面试题时小菜所写代码,见《小菜编程成长记(一)》)

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);}
}

大鸟: “吼吼,记住哦,编程是一门技术,更加是一门艺术,不能只满足于写完代码运行结果正确就完事,时常考虑如何让代码更加简炼,更加容易维护,容易扩展和复用,只有这样才可以是真的提高。写出优雅的代码真的是一种很爽的事情。不过学无止境,其实这才是理解面向对象的开始呢。给你出个作业,做一个商场收银软件,营业员根据客户购买商品单价和数量,向客户收费。”
        小菜:“就这个?没问题呀。”

(待续)

出处:http://www.cnblogs.com/cj723/archive/2006/09/23/512430.html

大话设计模式(五 体会简单工厂模式的美妙)相关推荐

  1. 大话设计模式Python实现-简单工厂模式

    简单工厂模式(Simple Factory Pattern):是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类. 下面使用简单工厂模式实现一个简单的四则运算 1 #!/us ...

  2. 23种设计模式 -----Day01:简单工厂模式

    目录 前言 1.设计模式(Design pattern)定义 2.为什么要使用设计模式(使用设计模式的意义) 3.设计原则 a.单一职责原则 b.开放封闭原则 c.里氏代换原则 d.迪米特法则 e.依 ...

  3. 【C#设计模式】4-0. 简单工厂模式【创建型】

    [C#设计模式]总目录-共23种 [C#设计模式]简单工厂模式 前言 一.简单工厂模式定义 二.实例 三.进一步研究[违反开闭原则的解决方法] 四.简化简单工厂模式[将抽象产品类和工厂类合并] 五.简 ...

  4. 设计模式 笔记4 | 简单工厂模式 在源码中的应用 | Calendar 日历 | 源码浅析 | 使用总结 | 建造者模式

    文章目录 一.Calendar 日历类 1.1 内部属性 1.2 设置时间属性值 1.3 获取时间属性 1.4 使用 Calander 计算时间 二.Calender 类中的设计模式 2.1 简单工厂 ...

  5. 从王者荣耀看设计模式(四.简单工厂模式)

    从王者荣耀看设计模式(简单工厂模式) 一.简介 游戏开始前,玩家可从英雄池自由挑选将要出战的英雄 二.简单工厂模式 简单工厂模式(Simple Factory Pattern)属于类的创新型模式,又叫 ...

  6. 【设计模式】之简单工厂模式详解与应用(一)

    开心一刻 [老公:老婆老婆,我刚去买了15块钱水果. 老婆:然后呢? 老公:给了老板100块,那二货找了我95.你说他二不二? 老公:我当时撒腿就跑啊. 老婆:水果呢? 老公:-忘拿了- 开心不,笑了 ...

  7. 手撕设计模式之「简单工厂模式」(Java描述)

    前言 利用简单工厂模式可以实现对象创建和业务逻辑处理的分离,但存在工厂类职责过重,增添新产品违背开闭原则等问题.它不属于GoF 23种设计模式之一,但是它可以作为学习工厂方法模式前的一个很好的引导. ...

  8. 设计模式----2(简单工厂模式的概念,简单工厂模式的实现,简单工厂模式的优缺点)

    简单工厂模式 简单工厂模式的概念 简单工厂模式属于类的创建型模式,又叫做静态工厂方法模式.通过专门定义一个类来负 责创建其他类的实例,被创建的实例通常都具有共同的父类. 具体分类 工厂(Creator ...

  9. 设计模式(1):简单工厂模式(Simple Factory Pattern)

    1. 从一个简单的例子开始 在众多的设计原则中,有一条原则是这么说的:要针对接口编程,不要针对实现编程. 针对接口编程的话,可以使用不同的实现类来创建这个对象.比如需要一个List: List< ...

最新文章

  1. (int),Int32.Parse() 和 Convert.toInt32() 的区别
  2. msflexgrid允许大选择_工程中要用多大的电线电缆?一文教你怎么算
  3. [Jmeter系列]Jmeter源码编译步骤(转)
  4. 汇编 and or xor not test cmp 条件跳转指令 jcc
  5. 修改android framework学习
  6. linux视频教程之vsftp_B
  7. Spring核心知识点总结
  8. qcom camera smmu 学习(3)
  9. “.NET研究”理解.NET程序集的执行过程
  10. eclipse优化方案
  11. Linux修改文件编码格式的三种方式
  12. java库存_java实现超市库存管理系统
  13. 传说中的考研神校,考研人数究竟有多高?
  14. cs系统的服务器地址,《反恐精英CS》服务器地址
  15. 发生系统错误 67,找不到网络名
  16. 【迁移学习】STL(Stratified Transfer Learning)小结
  17. 2015三十本好书推荐及理由
  18. 彩色飘带字体怎么制作?AE教程教给你
  19. 【Android】蓝牙开发——经典蓝牙:配对与解除配对 实现配对或连接时不弹出配对框
  20. 2019年上半年 DDOS流量攻击分析以及解决方案

热门文章

  1. [Linux]搜索文件是否包含指定内容并返回文件名
  2. Apache ZooKeeper - 使用ZK实现分布式锁(非公平锁/公平锁/共享锁 )
  3. Spring Boot2.x-11 使用@ControllerAdvice和@ExceptionHandler实现自定义全局异常
  4. Spring Cloud【Finchley】-07Feign构造多参数GET/POST请求
  5. Halcon知识:如何画出灰度图像直方图
  6. 2020-12-28 Matlab自动化控制-Adrc自抗扰控制
  7. mysql 事物gljbie_图片转成base64格式上传至数据库
  8. JAVA期末简答题参考
  9. 织女的红线_JAVA
  10. 精选30道Java笔试题解答