设计模式——简单工厂模式

与其明天开始,不如现在行动!

文章目录


简单工厂模式

现在我们要实现一个简单的计算器,输入两个数字,计算器能够完成加减乘除运算。

java 复制代码
public class SimpleFactory {
    public static void main(String[] args) {
       try {
           Scanner sc = new Scanner(System.in);
           System.out.println("请输入第一个数字:");
           double numA = Double.parseDouble(sc.nextLine());
           System.out.println("请选择运算符号(+、-、*、/):");
           String strOperate = sc.nextLine();
           System.out.println("test:" + strOperate);
           System.out.println("请输入第二个数字:");
           double numB = Double.parseDouble(sc.nextLine());
           double res = 0;
           switch (strOperate) {
               case "+":
                   res = numA + numB;
                   break;
               case "-":
                   res = numA - numB;
                   break;
               case "*":
                   res = numA * numB;
                   break;
               case "/":
                   res = numA / numB;
                   break;
           }
           System.out.println("结果是:" + res);
       }catch (Exception e) {
           System.out.println("输入格式有误:" + e);
       }
    }
}

虽然我们实现了计算器的功能,但是可以发现一个问题:我们写出来的程序只是用计算机的方式去思考,而没有用到面向对象的思想。也就是说我们的程序只是满足了当前的需求,但是它不容易维护、不容易扩展、更不容易复用,所以这个代码还达不到高质量的要求。

假如我们需要把这个代码复用一下,就需要整个Ctrl+c,虽然现在看不出来改动有多麻烦,但是当代码多到一定程度,此时维护起来就会是一场灾难了。那么现在我们加入使用面向对象的封装的思想,让程序变得可复用。

我们写出来的程序可以分为两个部分:

  1. 界面逻辑,负责接收输入的参数和要运算的操作
  2. 业务逻辑,负责处理具体的运算操作

改造后的代码:

处理业务逻辑类:

java 复制代码
public class Operation {
    public static double getResult(double numA, double numB, String strOperate) {
        double res = 0;
        switch (strOperate) {
            case "+":
                res = numA + numB;
                break;
            case "-":
                res = numA - numB;
                break;
            case "*":
                res = numA * numB;
                break;
            case "/":
                res = numA / numB;
                break;
        }
        return res;
    }
}

界面逻辑类:

java 复制代码
public class SimpleFactory {
    public static void main(String[] args) {
       try {
           Scanner sc = new Scanner(System.in);
           System.out.println("请输入第一个数字:");
           double numA = Double.parseDouble(sc.nextLine());
           System.out.println("请选择运算符号(+、-、*、/):");
           String strOperate = sc.nextLine();
           System.out.println("test:" + strOperate);
           System.out.println("请输入第二个数字:");
           double numB = Double.parseDouble(sc.nextLine());
           double res = Operation.getResult(numA, numB, strOperate);
           System.out.println("结果是:" + res);
       }catch (Exception e) {
           System.out.println("输入格式有误:" + e);
       }
    }
}

我们将程序的一些方法和执行步骤隐藏起来,只开放外部接口。就好像一辆车,引擎就是封装好的部件,我们不需要知道引擎的工作原理,只需要知道踩油门就会发送指令,车子就会走是一样的。现在的程序不管是在web程序还是app程序,都可以复用这个运算类(Operation类)。

现在的程序虽然做到了可复用,但是还没有达到可以灵活的修改和扩展,如果我要加一个指数的运算,就意味着我需要在原来的代码中去修改。此时我们可以利用面向对象的继承思想来修改代码,让其变得可灵活修改和扩展。

改造后的代码:

Operation运算类:

java 复制代码
public class Operation {
    public double getResult(double numA, double numB) {
        return 0;
    }
}

加减乘除类:

java 复制代码
public class Add extends Operation{
    @Override
    public double getResult(double numA, double numB) {
        return numA + numB;
    }
}
java 复制代码
public class Sub extends Operation{
    @Override
    public double getResult(double numA, double numB) {
        return numA - numB;
    }
}
java 复制代码
public class Mul extends Operation{
    @Override
    public double getResult(double numA, double numB) {
        return numA * numB;
    }
}
java 复制代码
public class Div extends Operation{
    @Override
    public double getResult(double numA, double numB) {
        if (numB == 0) {
            System.out.println("除数不能为0!");
            throw new ArithmeticException();
        }
        return numA / numB;
    }
}

上述程序中的加减乘除操作都继承了运算抽象类,并重写了其中的运算方法。但是这样就有一个问题了,怎么让计算器知道需要创建的是哪个对象呢?

接下来进入正题:简单工厂模式。在上述程序中,我们只要根据用户输入的运算操作,来实例化对应的运算类对象。那么怎么才能让计算器自己根据运算符去实例化对象,且不会增加多余的实例化对象。我们可以用一个单独的类来做这个创造实例的过程。

改造后的代码:

简单运算工厂类:

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

界面逻辑类:

java 复制代码
public class SimpleFactory {
    public static void main(String[] args) {
       try {
           Scanner sc = new Scanner(System.in);
           System.out.println("请输入第一个数字:");
           double numA = Double.parseDouble(sc.nextLine());
           System.out.println("请选择运算符号(+、-、*、/):");
           String strOperate = sc.nextLine();
           System.out.println("test:" + strOperate);
           System.out.println("请输入第二个数字:");
           double numB = Double.parseDouble(sc.nextLine());

           double res = OperationFactory.createOperation(strOperate).getResult(numA, numB);

           System.out.println("结果是:" + res);
       }catch (Exception e) {
           System.out.println("输入格式有误:" + e);
       }
    }
}

上述程序,使用了简单工厂和多态来让程序自己根据运算符实例化对象。现在我们的代码不管是在控制台、web程序、App程序都可以用,如果我们需要增加别的运算操作,只需要增加对应的运算子类和增加运算工厂类中的switch分支。

上述程序结构图:


💎总结

本文中若是有出现的错误请在评论区或者私信指出,我再进行改正优化,如果文章对你有所帮助,请给博主一个宝贵的三连,感谢大家😘!!!


相关推荐
「QT(C++)开发工程师」8 分钟前
C++11三大核心特性深度解析:类型特征、时间库与原子操作
java·c++·算法
乐分启航14 分钟前
SliMamba:十余K参数量刷新SOTA!高光谱分类的“降维打击“来了
java·人工智能·深度学习·算法·机器学习·分类·数据挖掘
yoothey1 小时前
Java字节流与字符流核心笔记(问答+考点复盘)
java·开发语言·笔记
black方块cxy2 小时前
实现一个输入框多个ip以逗号分隔最多20组,且ip不能重复
java·服务器·前端
23.2 小时前
【Java】char字符类型的UTF-16编码解析
java·开发语言·面试
怒放吧德德2 小时前
Spring Boot实战:InfluxDB 2.x简单教程
java·spring boot·后端
indexsunny2 小时前
互联网大厂Java面试实战:核心技术与业务场景深度解析
java·spring boot·hibernate·security·microservices·interview
是小蟹呀^2 小时前
Java中的继承:从入门到精通
java·继承
bearpping3 小时前
怎么下载安装yarn
java
西门吹雪分身3 小时前
JDK8之四大核心函数式接口
java·函数式接口