Big talk design pattern - simple factory pattern

process oriented

Requirement: Use Java to implement a calculator console program that requires inputting two numbers and operators to get the result.

1) Simple implementation

public static void version1() {
    
    
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入数字A:");
        int A = scanner.nextInt();
        System.out.println("请输入数字B:");
        int B = scanner.nextInt();
        System.out.println("请输入运算符号(+、-、*、/):");
        String oper = scanner.next();
        int result = 0;
        if (oper.equals("+")) {
    
     // 问题1:分支判断写法不好,计算机做了3次无用功
            result = A + B;
        }
        if (oper.equals("-")) {
    
    
            result = A - B;
        }
        if (oper.equals("*")) {
    
    
            result = A * B;
        }
        if (oper.equals("/")) {
    
    
            result = A / B; // 问题2:如果除数时输入0如何处理,输入的是字符符号不是数字如何处理
        }
        System.out.println("结果是:" + result);
    }

Existing problems:

  1. The writing of branch judgment is not good, which makes the computer do 3 times of useless work
  2. What if you enter 0 when dividing? What to do if the input is a character symbol instead of a number?

2) Improvement

  1. Branch transformation with switch
  2. Added divisor judgment, added try...catch
 public static void version2() {
    
    
        try {
    
    
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入数字A:");
            int A = scanner.nextInt();
            System.out.println("请输入数字B:");
            int B = scanner.nextInt();
            System.out.println("请输入运算符号(+、-、*、/):");
            String oper = scanner.next();
            int result = 0;
            switch (oper) {
    
    
            case "+":
                result = A + B;
                break;
            case "-":
                result = A - B;
                break;
            case "*":
                result = A * B;
                break;
            case "/":
                if (B != 0) {
    
    
                    result = A / B;
                } else {
    
    
                    throw new IllegalArgumentException("除数不能为0");
                }
                break;
            }
            System.out.println("结果是:" + result);
        } catch (Exception e) {
    
    
            System.out.println("您的输入有误:" + e.getMessage());
        }
    }

The above is just to realize the function, but it is actually thinking in the way of a computer. For example, the program requires the input of two numbers and operator symbols, and then judges and chooses how to operate according to the operator symbols, and obtains the result, which is not wrong in itself. However, this kind of thinking makes our program only meet the current needs, and the program is not easy to [maintain], not easy to [extend], and even more difficult to [reuse], thus failing to meet the high-quality requirements.

object oriented

Requirement: It is required to write another Windows calculator. Can the above code be reused?

1) Simple implementation

When there is a certain level of repetitive code in the code, maintenance can be a disaster. The bigger the system, the more serious the problem. There is a principle in programming, to avoid duplication as much as possible, and consider what is related to the calculator and what is not related to the console. Separate business logic from interface logic and reduce the coupling between them.

/**
 * 运算类(Operation):
 * 在Windows程序、Web版程序、PDA、手机等需要移动系统的软件需要运算都可以用它。
 */
public class Operation {
    
    
    public static double getResult(double A, double B, String operate) {
    
    
        double result = 0d;
        switch (operate) {
    
    
        case "+":
            result = A + B;
            break;
        case "-":
            result = A - B;
            break;
        case "*":
            result = A * B;
            break;
        case "/":
            result = A / B;
            break;
        }
        return result;
    }
}

Client code:

    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入数字A:");
        int A = scanner.nextInt();
        System.out.println("请输入数字B:");
        int B = scanner.nextInt();
        System.out.println("请输入运算符号(+、-、*、/):");
        String oper = scanner.next();
        double result = Operation.getResult(A, B, oper);
        System.out.println("结果是:"+result);
    }

2) Improvement

Q: If I want to add a root operation, how can I modify it?
Answer: You only need to change the Operation class, just add a branch to the switch.

The problem is that if you want to add a square root operation, you need to make the addition, subtraction, multiplication and division operations involved in the compilation. If you accidentally change the addition to the subtraction, isn't it bad. Originally let you add a function, but let the function code that runs well change, the risk is too great. Therefore , operations such as addition, subtraction, multiplication and division should be separated. Modifying them should not affect the other ones, and adding operation algorithms will not affect other codes .

public abstract class Operation {
    
    
    private double numberA = 0;
    private double numberB = 0;
    
    /**
     * 子类实现运算操作
     */
    public abstract double getResult();

    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 class OperationAdd extends Operation {
    
    
    @Override
    public double getResult() {
    
    
        return getNumberA() + getNumberB();
    }
}
// 减
public class OperationSub extends Operation {
    
    
    @Override
    public double getResult() {
    
    
        return getNumberA() - getNumberB();
    }
}
// 乘
public class OperationMul extends Operation {
    
    
    @Override
    public double getResult() {
    
    
        return getNumberA() * getNumberB();
    }
}
// 除
public class OperationDiv extends Operation {
    
    
    @Override
    public double getResult() {
    
    
        if (getNumberB() == 0) {
    
    
            throw new IllegalArgumentException("除数不能为0");
        }
        return getNumberA() / getNumberB();
    }
}

3) Simple Factory Pattern

How do I let the calculator know which algorithm I want to use? Use the simple factory pattern.
Who is to be instantiated? Will there be more instantiated objects in the future, such as adding root-causing operations
? This is a place that is easy to change. You should consider using a separate class for the process of creating instances, which is the factory.

public class OperationFactory {
    
    
    public static Operation createOperate(String operate) {
    
    
        Operation oper = null;
        switch (operate) {
    
    
        case "+":
            oper = new OperationAdd();
            break;
        case "-":
            oper = new OperationSub();
            break;
        case "*":
            oper = new OperationMul();
            break;
        case "/":
            oper = new OperationDiv();
            break;
        }
        return oper;
    }
}

Client class:
only need to input the operation symbol, the factory will instantiate the appropriate object, and realize the result of the calculator by returning the parent class through polymorphism.
If you want to modify it: 1: Add an operation subclass 2: In the factory class add switch branch

 public static void main(String[] args) {
    
    
    Operation oper= OperationFactory.createOperate("+");
    oper.setNumberA(1);
    oper.setNumberB(2);
    double result = oper.getResult();
    System.out.println(result);
}

Guess you like

Origin blog.csdn.net/fengsheng5210/article/details/123965979