zoukankan      html  css  js  c++  java
  • 第一章 简单工厂模式 (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
    

    小结

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

  • 相关阅读:
    PHP | 运算符优先级
    Docker配置PHP+Nginx+MySQL
    Windows下Mysql主从配置
    php-fpm重启配置修改无效
    MySQL事务
    hadoop伪集群搭建
    Springboot2.x源码下载安装
    微服务——服务之间访问,用Feign请求服务接口超时如何解决?
    Lua安装
    日期——计算每月第一天和最后一天
  • 原文地址:https://www.cnblogs.com/liuxiany/p/12633242.html
Copyright © 2011-2022 走看看