设计模式之美-简单工厂模式

一文带你学习简单工厂模式

场景:

请用任意一种面向对象语言实现一个计算器控制台程序,要求输入两个数和运算符号,得到结果。
在这里插入图片描述

解析:

就单纯实现一个简单计算器控制程序而言,这是一个很简单的功能,相信大家听到这个问题的时候,基本就已经有了思路了。

  1. 用户输入需要计算的值和计算方式。
  2. 程序根据用户输入内容进行计算。
  3. 输出答案。

实现:

public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in); //获取用户输入对象
        System.out.println("请输入数字A:");
        String a = scanner.nextLine();            //接收用户输入值
        System.out.println("请输入运算符号(+,-,*,/)");
        String b = scanner.nextLine();
        System.out.println("请输入数字B");
        String c = scanner.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);
    }

思考

  1. 其中代码规范咱就不说了,基本功能是已经实现了。
  2. 但是其中问题点也挺多的,代码不规范咱就不说了。
  3. 相信不少人已经开出来了,这段代码虽然简单实现了功能,
    但是程序却不容易维护,不容易扩展,不容易复用。
    好的程序

show time

  1. 1 业务的封装
    让业务逻辑与界面逻辑分开,让它们之间的耦合度降低,只有分离开,才可以达到更容易维护和扩展。

Operation运算类:
将运算的逻辑单独封装起来

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;
   }

}

此时客户端的代码也要进行相应的修改:
可以直接使用封装的运算方法了

public class run02 {

   public static void main(String[] args) {

       Scanner scanner = new Scanner(System.in); //获取用户输入对象
       System.out.println("请输入数字A:");
       double numberA = Double.parseDouble(scanner.nextLine()); //接收用户输入值
       System.out.println("请输入运算符号(+,-,*,/)");
       String operate = scanner.nextLine();
       System.out.println("请输入数字B");
       double numberB = Double.parseDouble(scanner.nextLine());
       double result = 0d;

       result = Operation.getResult(numberA,numberB,operate);

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

1.2 问题升级
假如我想再增加一个运算方式该怎么办呢?比如说增加一个指数的运算。
相信不少的小伙伴都会想到直接到封装的运算方法中进行增加一个case就行了,但是我们想,这样自然是可以实现方法,但是你增加了一个运算方法,是不是相当于整个运算的逻辑,例如 operation中的getResult方法整个的都需要进行编译,是不是就相当于影响到其他运算方法了。

所以我们要让程序变成这样,我们新增一个算法逻辑,并不能影响其他的运算逻辑,最好就是将每个逻辑都分开,这个自己管自己谁也不管誰,这就是松耦合。

1.3 继承和多态
1.3.1
我新建一个抽象类

将运算方法定义为一个抽象方法

public abstract class Operation03 {

   /**
    * 创建抽象方法
    * @param numberA
    * @param numberB
    * @return
    */
   public double getResult(double numberA, double numberB) { //这是一个抽象方法
       return 0d;
   }

}

1.3.2

然后将具体的运算方法继承这个抽象方法。

public class Add extends Operation03{

    public double getResult(double numberA,double numberB){
        return numberA + numberB;
    }
}
public class Sub extends Operation03{

    public double getResult(double numberA,double numberB){
        return numberA - numberB;
    }
}
public class Mul extends Operation03{

    public double getResult(double numberA,double numberB){
        return numberA * numberB;
    }
}
public class Div extends Operation03{

    public double getResult(double numberA,double numberB){
        if(numberB == 0){
            System.out.println("除数不能为0");
            throw new ArithmeticException();
        }
        return numberA / numberB;
    }
}

我们将所有的运算方式都使用子类集成抽象方法,具体的实现方式都在子类进行实现,但是貌似我们程序并不能直接的知道使用什么运算方法。
不知道如何去实例化对象。
ok,接下来就是正正的工厂了。

到底要实例化谁,将来会不会增加实例化的对象,比如增加指数运算,这是很容易变化的地方,应该用一个单独的类做这个创造示例的过程,这就是工厂

客户端代码变成了:

public class run03 {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in); //获取用户输入对象
        System.out.println("请输入数字A:");
        double numberA = Double.parseDouble(scanner.nextLine()); //接收用户输入值
        System.out.println("请输入运算符号(+,-,*,/)");
        String operate = scanner.nextLine();
        System.out.println("请输入数字B");
        double numberB = Double.parseDouble(scanner.nextLine());
        double result = 0d;

        Operation03 oper = OperationFactory.createOperate(operate);
        result = oper.getResult(numberA,numberB);

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

总结

这样一修改之后的有点就很显而易见了。

  1. 修改和维护运算方法的代码就很简单了。
  2. 他们之间的联系也更少了,耦合度没这么高了。
  3. 之后新增运算方式,直接新增一个运算子类就好了。
  4. 这个就是结构类图了。结构类图

最后

本文代码在gitee仓库中已经有了,各位小伙伴需要的可以自取
链接: gitee仓库连接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值