聊聊设计模式--简单工厂模式

简单工厂模式

​ 前面也学了很多各种微服务架构的组件,包括后续的服务部署、代码管理、Docker等技术,那么作为后端人员,最重要的任务还是代码编写能力,如何让你的代码写的漂亮、易扩展,让别人一看赏心悦目,那么设计模式就是很重的了。那么本本篇文章就来聊聊一个简单的工厂模式。

缘起

​ 一个22岁刚毕业的大学生A,计算机专业学的Java语言,到B公司面试。而面试题非常简单,实现一个简易计算器的功能,A觉得面试题很简单,三下五除二直接10分钟完事儿了。然而交卷后,迟迟等不到B公司的通知,多半是凉了,那么他是怎么实现的呢?代码如下:

java 复制代码
public class Test {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入数字A:");
        String A = sc.nextLine();
        System.out.println("请选择运算符(+、-、*、/):");
        String B = sc.nextLine();
        System.out.println("请输入数字B:");
        String C = sc.nextLine();
        double D = 0d;
        
        if (B.equals("+")) D = Double.parseDouble(A) + Double.parseDouble(C);
        if (B.equals("-")) D = Double.parseDouble(A) - Double.parseDouble(C);
        if (B.equals("*")) D = Double.parseDouble(A) * Double.parseDouble(C);
        if (B.equals("/")) D = Double.parseDouble(A) / Double.parseDouble(C);

        System.out.println("结果是:" + D);

    }
    
}

那么就以上的代码,按功能来说,有问题吗?

没问题,功能确实实现了;但是细看就会发现代码规范及其他的问题:

  • 变量名命名问题:ABCD?
  • if判断问题,假如输入的是+号,那么其他的判断还有必要再去执行吗,没必要
  • 输入的不是数字时怎么处理

那么按照上面的问题,依次去改动代码

java 复制代码
public class Test {

    public static void main(String[] args) {
        try {
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入数字A:");
            double numberA = Double.parseDouble(sc.nextLine());
            System.out.println("请选择运算符(+、-、*、/):");
            String strOperate = sc.nextLine();
            System.out.println("请输入数字B:");
            double numberB = Double.parseDouble(sc.nextLine());
            double result = 0d;
            switch (strOperate) {
                case "+":
                    result = numberA + numberB;
                    break;
                case "-":
                    result = numberA - numberB;
                    break;
                case "*":
                    result = numberA * numberB;
                    break;
                case "/":
                    result = numberA / numberB;
                    break;
            }
            System.out.println("结果是:" + result);
        } catch (Exception e) {
            System.out.println("您的输入有误:" + e.getMessage());
        }
    }

}

行了,代码规范的问题是都已经完善了。

那么如何提高代码的可维护、可扩展、可复用、灵活性更好呢?

答案就是面向对象。

业务的封装

准确的说,就是让业务逻辑和界面逻辑分开,让它们之间的耦合度下降,只有分离开,才可以达到容易维护和扩展。

增加一个运算类

java 复制代码
public class Operation {
    
    public static double getResult(double numberA, double numberB, String operate) {
        double result = 0d;
        switch (operate) {
            case "+":
                result = numberA + numberB;
                break;
            case "-":
                result = numberA - numberB;
                break;
            case "*":
                result = numberA * numberB;
                break;
            case "/":
                result = numberA / numberB;
                break;
        }
        return result;
    }
    
}

那么客户端Test的代码

java 复制代码
public class Test {

    public static void main(String[] args) {
        try {
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入数字A:");
            double numberA = Double.parseDouble(sc.nextLine());
            System.out.println("请选择运算符(+、-、*、/):");
            String strOperate = sc.nextLine();
            System.out.println("请输入数字B:");
            double numberB = Double.parseDouble(sc.nextLine());
            double result = Operation.getResult(numberA, numberB, strOperate);
            System.out.println("结果是:" + result);
        } catch (Exception e) {
            System.out.println("您的输入有误:" + e.getMessage());
        }
    }

}

业务逻辑和界面逻辑都分离开了,那么这种方案就是面向对象的封装,三大特性之一。

增加功能

计算器的功能发生改变了,不仅要支持+-*/,我还想要加一个平方根运算,那我们就需要去修改Operation类中的代码

java 复制代码
public class Operation {

    public static double getResult(double numberA, double numberB, String operate) {
        double result = 0d;
        switch (operate) {
            case "+":
                result = numberA + numberB;
                break;
            case "-":
                result = numberA - numberB;
                break;
            case "*":
                result = numberA * numberB;
                break;
            case "/":
                result = numberA / numberB;
                break;
            case "pow":
                result = Math.pow(numberA, numberB);
                break;
        }
        return result;
    }
}

那么问题来了,我这里是加了一个pow的case分支,加一个平方根运算的功能,但是却需要让加减乘除的运算全都得来参与编译,万一一个不小心,把加法运算改成减法了,又没有注意到,直接给上生产环境了,这之后造成的问题能承担的了吗?

那么我们为了增加功能,而不让其他已经存在的功能有代码误改的风险。继续对业务方法进行改进.

我们将Operation类置为抽象类,让其他的加减乘除继承它,并且每一个功能都是一个单独的类实现自己的业务逻辑

java 复制代码
public abstract class Operation {
    public double getResult(double numberA, double numberB) {
        return 0d;
    }
}

加减乘除类

java 复制代码
public class Add extends Operation { // 加
    @Override
    public double getResult(double numberA, double numberB) {
        return numberA + numberB;
    }
}

public class Sub extends Operation { // 减
    @Override
    public double getResult(double numberA, double numberB) {
        return numberA - numberB;
    }
}

public class Mul extends Operation { // 乘
    @Override
    public double getResult(double numberA, double numberB) {
        return numberA * numberB;
    }
}

public class Div extends Operation { // 除
    @Override
    public double getResult(double numberA, double numberB) {
        if (numberB == 0) {
            System.out.println("除数不能为0");
            throw new RuntimeException();
        }
        return numberA / numberB;
    }
}

实现简单工厂

上面抽象出来一个操作类(Operation),并且有加减乘除的业务逻辑类,那么我如何得知,应该用哪个业务逻辑类呢?

这时候,我们就需要一个工厂类,工厂顾名思义就是用来加工的,我把原料放进去,工厂给我生产出来产品。

java 复制代码
public class OperationFactory {  
    public static Operation createOperate(String operate) {
        Operation oper = null;
        switch (operate) {
            case "+":
                oper = new Add();
                break;
            case "-":
                oper = new Sub();
                break;
            case "*":
                oper = new Mul();
                break;
            case "/":
                oper = new Div();
                break;
        }
        return oper;
    }
}

客户端这里调用时

java 复制代码
public class Test {

    public static void main(String[] args) {
        try {
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入数字A:");
            double numberA = Double.parseDouble(sc.nextLine());
            System.out.println("请选择运算符(+、-、*、/):");
            String strOperate = sc.nextLine();
            System.out.println("请输入数字B:");
            double numberB = Double.parseDouble(sc.nextLine());
            Operation operate = OperationFactory.createOperate(strOperate);
            double result = operate.getResult(numberA, numberB);
            System.out.println("结果是:" + result);
        } catch (Exception e) {
            System.out.println("您的输入有误:" + e.getMessage());
        }
    }

}

上面就是大致的结构图,当我们再次增加新的功能时,只需要去集成Operation运算类,然后实现自己的业务逻辑就可以了,看起来是不是比原先的一坨代码更加一目了然了,并且也提高了它的复用性、维护性、扩展性,也更加灵活了。

相关推荐
wellc29 分钟前
SpringBoot集成Flowable
java·spring boot·后端
Hui Baby1 小时前
springAi+MCP三种
java
hsjcjh1 小时前
【MySQL】C# 连接MySQL
java
敖正炀1 小时前
LinkedBlockingDeque详解
java
wangyadong3171 小时前
datagrip 链接mysql 报错
java
untE EADO1 小时前
Tomcat的server.xml配置详解
xml·java·tomcat
ictI CABL2 小时前
Tomcat 乱码问题彻底解决
java·tomcat
敖正炀2 小时前
DelayQueue 详解
java
敖正炀2 小时前
PriorityBlockingQueue 详解
java
shark22222222 小时前
Spring 的三种注入方式?
java·数据库·spring