首页 > 学院 > 开发设计 > 正文

《大话设计模式》读书札记之简单工厂模式

2019-11-06 08:06:36
字体:
来源:转载
供稿:网友

题目描述

请用C++,java,C#任意一种面向对象语言来实现一个计算器控制台程序,要求输入两个数和运算符号,然后得到结果!

初步解题方法

很多像我这样刚毕业的计算机相关专业的学生一看到这个题目肯定是心中暗自窃喜,心想这么简单,于是他们很容易的就写下了以下的代码:

package test1;import java.util.Scanner;/** * Java设计模式 CalculatorOne.java * 作者:白芷 * 时间:2017/3/2 * 说明:简单计算器1.0版本 * */public class CalculatorOne { public static void main(String[] args) { double a,b,c; String sign; Scanner input=new Scanner(System.in); System.out.PRintln("请输入数字A:"); a=input.nextDouble(); System.out.println("请输入运算符号(+,-,*,/):"); sign=input.next(); System.out.println("请输入数字B:"); b=input.nextDouble(); if(sign.equals("+")){ c=a+b; }else if(sign.equals("-")){ c=a-b; }else if(sign.equals("*")){ c=a*b; }else{ c=a/b; } System.out.println("结果是:"+c); }}

缺陷分析

我们来看一下一些非常直观的缺陷:

以a,b,c这样的命名不规范,使得代码难以读懂。 使用if进行判断,显得程序有些混乱,条理不那么清晰。 未对除法运算的除数进行限制(用户输入0,系统就会崩溃)。

优化解题方法

针对以上的问题,我们对程序进行优化,得到如下的代码:

package test1;import java.util.Scanner;/** * Java设计模式 CalculatorTwo.java * 作者:白芷 * 时间:2017/3/3 * 说明:简单计算器2.0版本 * */public class CalculatorTwo { public static void main(String[] args) { // TODO Auto-generated method stub double numberA, numberB, result = 0; String sign; Scanner input = new Scanner(System.in); try { System.out.println("请输入数字A:"); numberA = input.nextDouble(); System.out.println("请输入运算符号(+,-,*,/):"); sign = input.next(); System.out.println("请输入数字B:"); numberB = input.nextDouble(); switch (sign) { case "+": result = numberA + numberB; break; case "-": result = numberA - numberB; break; case "*": result = numberA * numberB; break; case "/": if(numberB==0){ System.out.println("除数不能为零"); return; } result = numberA / numberB; break; } System.out.println("结果是:" + result); } catch (Exception e) { System.out.println("输入错误"); } }}

以上就是改进后的程序,貌似比第一个程序的健壮性要强很多了,但是这个程序会帮你拿到Offer吗?答案显然是No。 我们仔细审题就会发现,题目特意提到了用面向对象语言来解决这个问题,所以说,我们得用面向对象思想来解决这个问题,对应更改后的代码如下:

package test1;import java.util.Scanner;/** * Java设计模式 CalculatorThree.java * 作者:白芷 * 时间:2017/3/3 * 说明:简单计算器3.0版本 */class Operation { public static Double getResult(double numberA, double numberB, String sign) { Double result = null; switch (sign) { case "+": result = numberA + numberB; break; case "-": result = numberA - numberB; break; case "*": result = numberA * numberB; break; case "/": if (numberB == 0) { System.out.println("除数不能为零"); } result = numberA / numberB; break; } return result; }}public class CalculatorThree { public static void main(String[] args) { // TODO Auto-generated method stub Double numberA, numberB, result; String sign; Scanner input = new Scanner(System.in); try { System.out.println("请输入数字A:"); numberA = input.nextDouble(); System.out.println("请输入运算符号(+,-,*,/):"); sign = input.next(); System.out.println("请输入数字B:"); numberB = input.nextDouble(); result = Operation.getResult(numberA, numberB, sign); if (result != null) { System.out.println("结果是:" + result); } } catch (Exception e) { System.out.println("输入错误"); } }}

上面的程序差不多是一个面向对象的入门级程序了,运用了面向对象的三大特性之一:封装。将运算封装到了一个静态函数中去! 提出问题:怎样在在这个程序中运用另外两个特性继承和多态呢? 我们可把运算类写成一个父类,在向下派生出加法,减法,乘法以及除法类,看如下的改进代码: 首先看运算类(Operation.java):

package factory;abstract class Operation { private Double numberA; private Double numberB; public Double getNumberA() { return numberA; } public void setNumberA(double numberA) { this.numberA = numberA; } public Double getNumberB() { return numberB; } public void setNumberB(double numberB) { this.numberB = numberB; } public abstract Double getResult();}class OperationAdd extends Operation { @Override public Double getResult() { return this.getNumberA() + this.getNumberB(); }}class OperationSub extends Operation { @Override public Double getResult() { return this.getNumberA() - this.getNumberB(); }}class OperationMul extends Operation { @Override public Double getResult() { return this.getNumberA() * this.getNumberB(); }}class OperationDiv extends Operation { @Override public Double getResult() { if (this.getNumberB() == 0) { System.out.println("除数不能为零!"); return null; } return this.getNumberA() / this.getNumberB(); }}

在这里我们引出“简单工厂模式”,我们应该用一个单独的类来管理运算,以防止程序后面增加开根号或者开平方的需求。这个类就是工厂类,对应代码如下(OperationFactory.java):

package factory;public class OperationFactory { public static Operation setOperationSign(String sign) { switch (sign) { case "+": return new OperationAdd(); case "-": return new OperationSub(); case "*": return new OperationMul(); case "/": return new OperationDiv(); } return null; }}

最后就是计算器的客户段代码了,读到这里你会发现,只要上面的代码写好了,不管客户端是控制台程序,还是GUI程序都是可以复用上面的代码的,如下(FinalCaculator.java):

package factory;import java.util.Scanner;/** * Java设计模式 FinalCaculator.java * 作者:白芷 * 时间:2017/3/3 * 说明:简单计算器4.0版本 */public class FinalCaculator { public static void main(String[] args) { Operation oper = null; Double numberA, numberB, result; String sign; Scanner input = new Scanner(System.in); try { System.out.println("请输入数字A:"); numberA = input.nextDouble(); System.out.println("请输入运算符号(+,-,*,/):"); sign = input.next(); System.out.println("请输入数字B:"); numberB = input.nextDouble(); oper = OperationFactory.setOperationSign(sign); oper.setNumberA(numberA); oper.setNumberB(numberB); result=oper.getResult(); if (result != null) { System.out.println( result); } } catch (Exception e) { System.out.println("输入错误"); } }}

以上就是这个问题用面向对象思想实现的完整解答了!

总结

一个看似简单的问题其中也是有很大的学问的。希望我们成为一个软件工程师而不是代码的搬运工!


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表