(续上篇)次日,小菜再来找大鸟,问道:“你昨天说计算器这样的小程序还可以用到面向对象三大特性?继承和多态怎么可能用得上,我实在不可理解。”大鸟:“小菜很有钻研精神嘛!好,今天我让你功力加深一级。你先要考虑一下,你昨天写的这个代码,能否做到很灵活的可修改和扩展呢?”小菜:“我已经把业务和界面分离了呀,这不是很灵活了吗?”大鸟:“那我问你,现在如果我希望增加一个开根(sqrt)运算,你如何改?”小菜:“那只需要改Operation类就行了,在switch中加一个分支就行了。”大鸟:“问题是你要加一个平方根运算,却需要把加减乘除的运算都得来参与编译,如果你一不小心,把加法运算改成了减法,这不是大大的糟糕。
打个比方,如果现在公司要求你为公司的薪资管理系统做维护,原来只有技术人员(月薪),市场销售人员(底薪+提成),经理(年薪+股份)三种运算算法,现在要增加兼职工作人员的(时薪)算法,但按照你昨天的程序写法,公司就必须要把包含有的原三种算法的运算类给你,让你修改,你如果心中小算盘一打,‘TMD,公司给我的工资这么低,我真是郁闷,这会有机会了’,于是你除了增加了兼职算法以外,在技术人员(月薪)算法中写了一句:
那就意味着,你的月薪每月都会增加10%(小心被抓去坐牢),本来是让你加一个功能,却使得原有的运行良好的功能代码产生了变化,这个风险太大了。你明白了吗?”小菜:“哦,你的意思是,我应该把加减乘除等运算分离,修改其中一个不影响另外的几个,增加运算算法也不影响其它代码,是这样吗?”大鸟:“自己想去吧,如何用继承和多态,你应该有感觉了。”小菜:“OK,我马上去写。”
//运算类工厂publicclassOperationFactory{publicstringcreateOperate(stringoperate){Calculatorcalc=null;switch(operate){case"+":calc=newCalculatorAdd();break;case"-":calc=newCalculatorSub();break;case"*":calc=newCalculatorRide();break;case"/":calc=newCalculatorDiv();break;}returncalc;}}运算类工厂大鸟:“哈,看到吧,这样子,你只需要输入运算符号,工厂就实例化出合适的对象,通过多态,返回父类的方式实现了计算器的结果。”
//中间类publicclassOperation{publicstaticdoubleGetResult01(doublenumberA,doublenumberB,stringoperate){doubleresult=0d;Calculatorcalc=null;calc=OperationFactory.createOperate(operate);calc.NumberA=numberA;cal.NumberB=numberB;result=calc.GetResult();returnresult;}}中间类大鸟:“哈,界面的实现就是这样的代码,不管你是控制台程序,Windows程序,Web程序,PDA或手机程序,都可以用这段代码来实现计算器的功能,当有一天我们需要更改加法运算,我们只需要改哪里?”小菜:“改OperationAdd就可以了。”大鸟:“那么我们需要增加各种复杂运算,比如平方根,立方根,自然对数,正弦余弦等,如何做?”小菜:“只要增加相应的运算子类就可以了呀。”大鸟:“嗯?够了吗?”小菜:“对了,还需要去修改运算类工厂,在switch中增加分支。”大鸟:“哈,那才对,那如果要修改界面呢?”小菜:“那就去改界面呀,关运算什么事呀。”
classInheritPoly{staticvoidMain(string[]args){try{Console.Write("请输入数字A:");stringstrNumberA=Console.ReadLine();Console.Write("请选择运算符号(+、-、*、/):");stringstrOperate=Console.ReadLine();Console.Write("请输入数字B:");stringstrNumberB=Console.ReadLine();stringstrResult="";strResult=Convert.ToString(Operation.GetResult01(Convert.ToDouble(strNumberA),Convert.ToDouble(strNumberB),strOperate);Console.WriteLine("结果是:"+strResult);Console.readLine();}catch(Exceptionex){Console.WriteLine("您这里输入有错:"+ex.Message);}}}界面实现小菜:“回想那天我面试题写的代码,我终于明白我为什么写得不成功了,原来一个小小的计算器也可以写出这么精彩的代码,谢谢大鸟。”
(下为当时面试题时小菜所写代码,见《小菜编程成长记(一)》)
classProgram{staticvoidMain(string[]args){Console.Write("请输入数字A:");stringA=Console.ReadLine();Console.Write("请选择运算符号(+、-、*、/):");stringB=Console.ReadLine();Console.Write("请输入数字B:");stringC=Console.ReadLine();stringD="";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);}}