工厂模式的应用--简单计算器

如果让你写一个简单的计算器,初学者:辣还不简单,看我的:

import java.util.Scanner;

public class MainClass {

    public static void main(String[] args) {

        System.out.println("请输入第一个操作数:");
        Scanner scanner = new Scanner(System.in);
        String num1 = scanner.nextLine();

        System.out.println("请输入操作符:");
        String oper = scanner.nextLine();

        System.out.println("请输入第二个操作数:");
        String num2 = scanner.nextLine();

        double result = 0.0;
        if ("+".equals(oper)) {
                result = Double.parseDouble(num1) + Double.parseDouble(num2);
            } else if ("-".equals(oper)) {
                result = Double.parseDouble(num1) - Double.parseDouble(num2);
            } else if ("*".equals(oper)) {
                result = Double.parseDouble(num1) * Double.parseDouble(num2);
            } else if ("/".equals(oper)) {
                result = Double.parseDouble(num1) / Double.parseDouble(num2);
            } else {
                result = -9999;
            }
        System.out.println(num1 + oper + num2 + "=" + result);

    }
}

搞定!!!呵呵。

既然学了设计模式,这样的代码是拿不出手的。如果让你新增一种计算方法,比如乘方运算,你在呢么办,只能再加个else if,这样的代码是没有可扩展性的。而且,一般情况下,main方法中写的主要是方法的调用,具体的业务逻辑的代码是不出现在main方法中的。这么说的话,上面的代码确实需要改进改进了。

我们想想能不能用前面的工厂方法模式呢?首先,加减乘除都是对操作数的计算,最后得到一个结果,我们可以将这个特征抽取出来,定义成一个父类Calculator.

//Calculator.java


public abstract class Calculator {

    private double num1;
    private double num2;
    public double getNum1() {
        return num1;
    }
    public void setNum1(double num1) {
        this.num1 = num1;
    }
    public double getNum2() {
        return num2;
    }
    public void setNum2(double num2) {
        this.num2 = num2;
    }

    public abstract double getResult();
}

然后我们如果我们就创建具体的运算类型继承这个父类即可,下面是加法、减法的实现:

//AddCalculator.java

public class AddCalculator extends Calculator{

    @Override
    public double getResult() {

        return this.getNum1()+this.getNum2();
    }

}
//SubCalculator.java

public class SubCalculator extends Calculator{

    @Override
    public double getResult() {

        return this.getNum1()-this.getNum2();
    }

}

然后,要想完成计算,我们必须创建相应的计算类型,对吧?想想,我们前面不是学习了简单工厂模式吗?我们可以定义一个工厂,根据传入的操作符类型new出相应的计算类型类呀。所以,下面我们顶一个工厂:

//CalculatorFactory.java

public class CalculatorFactory {

    public Calculator getCalclator (String type){

        if("+".equals(type)){
            return new AddCalculator();
        }else if ("-".equals(type)){
            return new SubCalculator();
        }

        return null;
    }

}

这样我们main方法中的代码就清爽多了:

public static void main(String[] args) {

        System.out.println("请输入第一个操作数:");
        Scanner scanner = new Scanner(System.in);
        String num1 = scanner.nextLine();

        System.out.println("请输入操作符:");
        String oper = scanner.nextLine();

        System.out.println("请输入第二个操作数:");
        String num2 = scanner.nextLine();

         double result = 0.0;
         CalculatorFactory cf = new CalculatorFactory();
         Calculator calc = cf.getCalclator(oper);
         calc.setNum1(Double.parseDouble(num1));
         calc.setNum2(Double.parseDouble(num2));
         result = calc.getResult();
         System.out.println(num1 + oper + num2 + "=" + result);

    }

现在,我们如果需要添加一个乘方运算,main方法需要改动吗?不需要。我们只要添加一个乘方运算的类继承自Calculator类,然后在CalculatorFactory 中添加一个else if判断,返回相应的计算类型实例即可。

是不是现在的代码比以前好多了。但是,你有木有觉得还不爽,每次都得改工厂中的代码,是不是很不爽,这违反了”封闭”的原则。是的,我们不还学了工厂方法模式吗?

我们可以将工厂做成一个接口,然后让特定的运算类型工厂实现这个接口,这样的话,即使增加新的运算类型,我们只要新建这个特殊类型的工厂即可。

所以,我们先修改CalculatorFactory,将其做成一个接口。

//CalculatorFactory.java
public interface CalculatorFactory {
    public Calculator getCalclator ();
}

然后派生出具体的类型工厂:

//AddFactory.java
public class AddFactory implements CalculatorFactory{

    @Override
    public Calculator getCalclator() {

        return new AddCalculator();
    }

}
//SubFactory.java
public class SubFactory implements CalculatorFactory{

    @Override
    public Calculator getCalclator() {
        // TODO Auto-generated method stub
        return new SubCalculator();
    }

}

这样,我们在main方法中就可以这么调用:(乘除方法就没实现了,只是先加减,各位看官懂意思就好。)

public static void main(String[] args) {

        System.out.println("请输入第一个操作数:");
        Scanner scanner = new Scanner(System.in);
        String num1 = scanner.nextLine();

        System.out.println("请输入操作符:");
        String oper = scanner.nextLine();

        System.out.println("请输入第二个操作数:");
        String num2 = scanner.nextLine();

        double result = 0.0;

        CalculatorFactory cf = null;
        if ("+".equals(oper)) {
            cf = new AddFactory();
            Calculator add = cf.getCalclator();
            add.setNum1(Double.parseDouble(num1));
            add.setNum2(Double.parseDouble(num2));
            result = add.getResult(); 

        } else if ("-".equals(oper)) {
            cf = new SubFactory();
            Calculator add = cf.getCalclator();
            add.setNum1(Double.parseDouble(num1));
            add.setNum2(Double.parseDouble(num2));
            result = add.getResult(); 
        } else if ("*".equals(oper)) {
            result = Double.parseDouble(num1) * Double.parseDouble(num2);
        } else if ("/".equals(oper)) {
            result = Double.parseDouble(num1) / Double.parseDouble(num2);
        } else {
            result = -9999;
        }

        System.out.println(num1 + oper + num2 + "=" + result);
    }

可能会有人说,那么你新增加一种运算类型,不还是修改main方法吗,是的这个是不可以避免的,但是,修改main方法中的代码比修改底层实现代码要强吧,你觉得呢?现在只要新增加一种运算类型,只要增加一个实现这个类型的算法(继承子Calculator),然后创建一个实例化这个算法的工厂接口(实现CalculatorFactory接口)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值