您好,欢迎访问三七文档
简单工厂模式软件设计求职小故事小菜今年计算机专业大四毕业,学了不少软件开发方面的东西,踌躇满志,一心要找一个好单位。投递简历后,收到一个单位的面试通知。到单位后,前台小姐给了他一分题目,上面写着:“请用C++、Java、C#等任意一种面向对象语言实现一个计算机控制台程序,要求输入两个数和运算符号,得到结果。”小菜一看,这还不简单,三下五除二,10分钟不到就写完了,感觉也没错,交卷后,前台小姐说一周内等通知吧。于是小菜满怀期待地等待,可半个月过去了,什么消息也没有,小菜很郁闷,我的代码明明实现了啊,为什么不给机会?23classProgram//小菜代码{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(B==/)D=Convert.ToString(Convert.ToDouble(A)/Convert.ToDouble(C));Console.Write(结果是:+D);}}且先撇开出题人的意思,这段代码有何不足?4classProgram//小菜代码{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(B==/)D=Convert.ToString(Convert.ToDouble(A)/Convert.ToDouble(C));Console.Write(结果是:+D);}}这样命名非常不规范,不成熟判断分支,这种写法意味着每个条件都要判断,等于计算机做了三次无用功若客户输入0呢?如果输入的是其他字符而非数字呢?5classProgram//小菜修改后代码{staticvoidMain(string[]args){try{Console.Write(请输入数字A:);stringstrNumberA=Console.ReadLine();Console.Write(请选择运算符(+-*/));stringstrOperate=Console.ReadLine();Console.Write(请输入数字B:);stringstrNumberB=Console.ReadLine();stringstrResult=;switch(strOperate){case+:strResult=Convert.ToString(Convert.ToDouble(..A)+Convert.ToDouble(..C));break;case-:strResult=Convert.ToString(Convert.ToDouble(..A)-Convert.ToDouble(..C));break;case*:strResult=Convert.ToString(Convert.ToDouble(..A)*Convert.ToDouble(..C));break;6classProgram//小菜修改后代码{staticvoidMain(string[]args){try{...switch(strOperate){.....case/:if(strNumberB!=0)strResult=Convert.ToString(Convert.ToDouble(..A)/Convert.ToDouble(..C));elsestrResult=除数不能为0;break;}//endswitchConsole.Write(结果是:+strResult);}//endtrycatch(Exceptionex){Console.WriteLine(输入有错+ex.Message);}//endcatch}//endMain}面向对象编程编程者容易遇到这样的问题。遇到问题直觉地用计算机能够理解的逻辑来描述和表达待解决问题及具体的求解过程。这其实是用计算机的方式去思考。比如计算器,先要去输入两个数和符号,然后根据符号去选择如何运算,得到结果。本身没错,但却使得程序只是为满足当前需求,不易维护,不易扩展,更不容易复用,从而达不到高质量代码的要求。什么叫易维护,易扩展,易复用呢?活字印刷,面向对象三国时期,曹操率领百万大军攻打东吴,大军在长江赤壁驻扎,军船连城一片,眼看就要灭掉东吴,统一天下,曹操大悦,于是大宴众文武,酒席间,曹操诗性打发,不觉吟道:“喝酒唱歌,人生真爽。......”。众文武齐呼:“丞相好诗!”于是一臣子速命印刷工匠刻版印刷,以便流传天下。喝酒唱歌,人生真爽。............活字印刷,面向对象样张出来给曹操一看,曹操感觉不妥,说道“喝与唱,此话过俗,应改为‘对酒当歌’较好!”。于是此臣就命工匠重新来过。工匠眼看连夜刻版之工,彻底白费,心中叫苦不迭。只得照办。喝酒唱歌,人生真爽。............对酒当歌,人生真爽。............喝酒唱歌,人生真爽。............活字印刷,面向对象样张再次出来给曹操过目,曹操细细一品,觉得还是不好,说:“人生真爽太过直接,应改问语才够意境,因此要改为‘对酒当歌,人生几何?......”。当臣子转告工匠时,工匠晕倒......对酒当歌,人生真爽。............对酒当歌,人生几何?............活字印刷,面向对象工匠为何会晕倒?三国时期还没有活字印刷,如果有了活字印刷,只需要更改四个字就可以,其余工作没有白做。喝酒唱歌人生真爽对当几何活字印刷,面向对象喝酒唱歌人生真爽对当几何第一,要改,只需更改要改之字,此为可维护。第二,这些字并非用完这次就无用,完全可以在后来的印刷中重复使用,此乃可复用。第三,此诗若要加字,只需另外加入即可,这是可扩展。第四,字的排列其实可能是竖排也可能是横排,只需要将活字移动就可满足要求,此是灵活性好。面向对象的好处满足客户需求变化。封装、继承、多态降低程序耦合度。(传统印刷术问题在于字都刻在一个面板上耦合度太高)公司出题本意是希望求职者写出容易维护、容易扩展、容易复用的计算机程序。复制VS复用初级程序员的工作就是Ctrl+C和Ctrl+V,这其实很不好的编程习惯。当代码中重复代码多到一定程度,维护时,就是一场灾难。编程有一原则,尽可能避免重复。业务的封装现在要求写一个Windows的计算器,那么小菜之前的代码可以复用吗?小菜:“那还不简单,直接代码复制过去不就可以?改动不大,不麻烦!”“想想看,小菜的代码那些与控制台有关哪些只和计算器有关?”小菜:“你的意思是分一个类出来?让计算和显示分开。”业务的封装让业务逻辑和界面逻辑分开,让它们之间的耦合度降低,只要分离开,可以达到容易维护和扩展。业务的封装publicclassOperation//运算类{publicstaticdoubleGetResult(doublenumberA,doublenumberB,stringoperate){doubleresult=0d;switch(operate){case+:result=numberA+numberB;break;case-:result=numberA-numberB;break;case*:result=numberA*numberB;break;case/:result=numberA/numberB;break;}returnresult;}}业务的封装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.GetResult(Convert.ToDouble(strNumberA),Convert.ToDouble(strNumberB),strOperate));Console.WriteLine(结果是:+strResult);}//endtrycatch(Exceptionex){Console.WriteLine(输入有错+ex.Message);}//endcatch}//endMain如果现在要写一个Windows的计算器,就可以复用运算类Operation。只实现了面向对象三大特征中的哪一种?紧耦合VS松耦合小菜:“计算器这样的小程序还可以用到面向对象三大特性,继承和多态怎么可能用上,我实在不能理解。”“小菜很有钻研精神嘛。你先考虑下,昨天那段程序除了可复用,还能否做到很灵活的可修改和可扩展呢?”小菜:“我已经把业务和界面分离了,不是很灵活了吗?”“那么,如果现在需要加上一个求根运算,要如何修改?”紧耦合VS松耦合小菜:“只需要Operation类就行了,在switch中加一个分支就好了。”只要加一个平方根,却需要加减乘除都来参与编写、编译,如果一不小心把加改成减法,岂不糟糕。紧耦合VS松耦合例如:公司要求小菜为公司薪金管理系统做维护,原来只有技术人员(月薪),市场销售人员(底薪+提成),经理(年薪+股份)三种运算算法,现在要增加兼职人员(时薪)的算法。若按照小菜之前的程序写法,公司必须把包含三种薪资算法的运算类给他,让他修改。如果小菜心中打小算盘,“我去,公司给我工资那么低,我真够郁闷的,这下有机会”。紧耦合VS松耦合于是小菜除了增加兼职算法外,在技术人员(月薪)算法中再多加一句if(员工是小菜){salary=salary*1.1;}这就意味着,小菜月薪每月提高10%,本来只是加一个功能,却使得原有的运行良好的功能代码发生变化,风险太大。紧耦合VS松耦合小菜:“哦,所以我应该把加减乘除等运算分离,修改其中一个不影响另外几个,增加运算算法也不影响其他代码。”业务的封装publicclassOperation//运算类{privatedouble_numberA=0;privatedouble_numberB=0;publicdoubleNumberA{get{return_numberA;}//外界
本文标题:1简单工厂模式
链接地址:https://www.777doc.com/doc-3850570 .html