第一章 简单工厂模式 (Simple Factory)

问题引入

如果说要通过代码写一个计算器,来代替加减乘除的笔算。那该怎么写呢?比如说可以写成这样:

public class Calculator {
    public static void main(String[] args) {

        double firstNumber = 0, secondNumber = 0;
        String sign = null;

        Scanner scanner = new Scanner(new BufferedInputStream(System.in));

        System.out.print("请输入第一个数字:");
        firstNumber = Double.valueOf(scanner.nextLine());

        System.out.print("请输入运算符:(+-*/)");
        sign = scanner.nextLine();

        System.out.print("请输入第二个数字:");
        secondNumber = Double.valueOf(scanner.nextLine());

        if ("+".equals(sign)) {
            System.out.println("计算结果为:" + (firstNumber + secondNumber));
        } else if ("-".equals(sign)) {
            System.out.println("计算结果为:" + (firstNumber - secondNumber));
        } else if ("*".equals(sign)) {
            System.out.println("计算结果为:" + (firstNumber * secondNumber));
        } else if ("-".equals(sign)) {
            System.out.println("计算结果为:" + (firstNumber / secondNumber));
        } else {
            System.out.println("不支持此运算");
        }

    }
}

暂时忽略掉参数校验,以及像是除数不能为空等这样的问题。这样就简单实现了计算器的功能,运行之后的结果,以加法为例:

请输入第一个数字:1
请输入运算符:(+-*/)+
请输入第二个数字:2
计算结果为:3.0ddddd

Process finished with exit code 0

目前计算器程序的问题:

  1. 提示语和运算的逻辑写到一块,耦合较高。
  2. 如果要添加新的运算,比如求平方,则需要修改Calculator类源码。可扩展性和可维护性较差。

问题解决

这样的程序可扩展性太差,耦合度较高,所以需要进行封装改造。代码如下:
将计算逻辑单独封装成一个类:

public class Operation {

    /**
     * 计算器运算方法
     *
     * @param number1  数字1
     * @param number2  数字2
     * @param operator 运算符
     * @return 运算结果
     */
    public double operation(double number1, double number2, String operator) {

        double result = 0;

        if ("+".equals(operator)) {
            result = number1 + number2;
        } else if ("-".equals(operator)) {
            result = number1 - number2;
        } else if ("*".equals(operator)) {
            result = number1 * number2;
        } else if ("-".equals(operator)) {
            result = number1 / number2;
        } else {
            System.out.println("不支持此运算");
        }

        return result;
    }
}

测试用例:

public class Calculator2Test {

    public static void main(String[] args) {
        double firstNumber = 0, secondNumber = 0;
        String sign = null;

        Scanner scanner = new Scanner(new BufferedInputStream(System.in));

        System.out.print("请输入第一个数字:");
        firstNumber = Double.valueOf(scanner.nextLine());

        System.out.print("请输入运算符:(+-*/)");
        sign = scanner.nextLine();

        System.out.print("请输入第二个数字:");
        secondNumber = Double.valueOf(scanner.nextLine());

        Operation operation = new Operation();
        double result = operation.operation(firstNumber, secondNumber, sign);

        System.out.println("计算结果为:" + result);
    }
}

这样就解决了,运算逻辑和提示语耦合的问题。下面解决下增加或者修改运算逻辑需要修改Operation类,会影响到其他运算的使用的问题。先说一下思路,抽象出一个运算接口,接口里定义一个运算的方法。然后建四个类去实现接口,分别是加减乘除类,然后重写其中的运算方法,实现自己的运算逻辑。这样的话,如果要添加新的运算,则只需要新建类去实现接口就好,并不会影响其他运算符的使用。代码如下:

运算接口:

public interface Operator {

    /**
     * 运算方法
     *
     * @param number1 数字1
     * @param number2 数字2
     * @return
     */
    double compute(double number1, double number2);
}

加减乘除类:

public class Addition implements Operator {

    public double compute(double number1, double number2) {
        return number1 + number2;
    }
}

public class Subtraction implements Operator {

    public double compute(double number1, double number2) {
        return number1 - number2;
    }
}

public class Multiplication implements Operator {

    public double compute(double number1, double number2) {
        return number1 * number2;
    }
}

public class Division implements Operator {

    public double compute(double number1, double number2) {

        if (number2 == 0) {
            System.out.println("除数不能为0");
        }

        return number1 / number2;
    }
}

运算符工厂类:

public class OperatorFactory {

    public Operator getOperator(String operator) {

        if ("+".equals(operator)) {
            return new Addition();
        } else if ("-".equals(operator)) {
            return new Subtraction();
        } else if ("*".equals(operator)) {
            return new Multiplication();
        } else if ("/".equals(operator)) {
            return new Division();
        } else {
            System.out.println("不支持此运算");
            return null;
        }
    }
}

这样就实现了封装和解耦,每个运算符之间互不影响,各自实现自己的运算逻辑。如果想添加一种新的运算逻辑,则只需要新建一个类去实现Operator接口,然后实现其中的运算方法,然后再工厂类的if判断加一个新的分支就好了。比之前的写法耦合度降低了,可扩展性提高了,也变得易于维护了。测试一下:

public class Calculator3Test {

    public static void main(String[] args) {
        OperatorFactory operatorFactory = new OperatorFactory();

        double firstNumber = 0, secondNumber = 0;
        String sign = null;

        Scanner scanner = new Scanner(new BufferedInputStream(System.in));

        System.out.print("请输入第一个数字:");
        firstNumber = Double.valueOf(scanner.nextLine());

        System.out.print("请输入运算符:(+-*/)");
        Operator operator = operatorFactory.getOperator(scanner.nextLine());

        System.out.print("请输入第二个数字:");
        secondNumber = Double.valueOf(scanner.nextLine());

        System.out.println("运算结果为:" + operator.compute(firstNumber, secondNumber));
    }
}

运行结果为:

请输入第一个数字:1
请输入运算符:(+-*/)/
请输入第二个数字:2
运算结果为:0.5

Process finished with exit code 0

如果想添加一个取余数的算法,则需要新建一个类去实现Operator接口,然后在工厂中添加一个if分支:

public class Remainder implements Operator {

    public double compute(double number1, double number2) {
        return number1 % number2;
    }
}

工厂类修改:

 public Operator getOperator(String operator) {

        if ("+".equals(operator)) {
            return new Addition();
        } else if ("-".equals(operator)) {
            return new Subtraction();
        } else if ("*".equals(operator)) {
            return new Multiplication();
        } else if ("/".equals(operator)) {
            return new Division();
        } else if ("%".equals(operator)) {
            return new Remainder();
        } else {
            System.out.println("不支持此运算");
            return null;
        }
    }

重新运行测试类:

请输入第一个数字:10
请输入运算符:(+-*/%)%
请输入第二个数字:3
运算结果为:1.0

Process finished with exit code 0

小结

简单工厂模式适用于解决对象的创建问题。

posted on 2020-04-04 18:52  liuxiany  阅读(99)  评论(0编辑  收藏  举报

导航