初识设计模式

235 阅读4分钟

一、简单工厂模式

我们以简单的计算器为例

level 1

拿到一个计算器的题目,大家一定会想到,使用switch判断符号,进入分支后计算

demo:

Operation.java
    public static Operation getResult(double numberA,double numberB,String operate){
        double result = 0;
        //判断类型,创建对象
        switch (operate){
            case "+":
                result = numberA + numberB;
                break;
            case "-":
                result = numberA - numberB;
                break;
            case "*":
                result = numberA * numberB;
                break;
            case "/":
                result = numberA / numberB;
                break;
            default:
                System.out.println("输入有误!请检查后重新输入!");
        }
        return result;
    }
    
Client.java
    public static void main(String[] args){
        //此处略去输入赋值
        double result = Operation.getResult(numberA,numberB,operate);
        System.out.println("计算结果为:"+result);
    }

这样一个简单的计算器就行写好了,但是你有没有发现一个问题,虽然将服务端和客户端进行了分离,但是如果需要完善这个计算器,增加新的运算方式,比如开平方的sqrt运算???如何解决??

解决方案:

更改Operation.java文件,在switch中增加一个分支。

结果:

1、这样仅仅是增加一个新的算法,却要使所有的算法都重新进行编译,也就是一个算法可以影响到所有的算法,这样使代码的
耦合度太高,不利于再次开发与维护。
2、另一方面就是每次增加功能点,你需要在集合了所有的算法的类中进行修改,一个失误操作可以让整个项目陷入泥潭

level 2

我们在level 1中的方案已经发现了他的利弊,那么如何来让自己的项目更加完善,使代码的耦合度降低,增大代码的可用性,可伸展性

我们可以试一试继承:

Operation.java
    package designpatterns.simplefactorymode.service;

    /**
     * @author :DengSiYuan
     * @date :2018/12/2 10:47
     * @desc : 该类是对数字的封装以及运算结果的处理
     */
    public class Operation {

        private double numberA = 0;
        private double numberB = 0;
  
        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 double getResult() throws Exception {
        double result = 0;
        return result;
    }
}

OperationAdd.java
    package designpatterns.simplefactorymode.service;

/**
 * @author :DengSiYuan
 * @date :2018/12/2 11:37
 * @desc :加法运算
 */
public class OperationAdd extends Operation {

    @Override
    public double getResult(){
        double result = 0;
        result = getNumberA() + getNumberB();
        return result;
    }

}

剩下的乘除亦然

这样使用继承,我们将所有运算共同需要的属性:两个数字和一个方法:算出结果,放入到他们共同的父类中,这样每次需要增加新的运算方式,只需要去继承这个Operation,如有其他特殊要求,进行扩展即可。

那么问题又来了:我们每次如何去判断这次是使用的什么运算方式(+?-?*?/),然后去创建相应的对象,这样我们就需要一个"工厂"来管理,举个例子:

我们去工厂告诉工厂主管说我们需要一个IPhone X,这时候他们知道了你所需要的手机类型后,告诉下面的工程师,创建了一个实体IPhone X对象。

程序中的工厂和现实中的一样,我们需要在程序的入口给工厂一个Type,他会根据你所告诉他的Type,创建一个你所需要使用的匹配的对象实体,调用使用他的方法

接下来我们来看Level 3

level 3

到了我们的重点:简单工厂模式

先看一下他的UML图吧

简单设计模式

这是一个简单的设计

start ---> OperationFactory ---> 判断类型,动态创建对象 ---> 确切的知道那个类,使用其方法

Operation.java(所有运算的父类)

package designpatterns.simplefactorymode.service;

/**
 * @author :DengSiYuan
 * @date :2018/12/2 10:47
 * @desc : 该类是对数字的封装以及运算结果的处理
 */
public class Operation {

    private double numberA = 0;
    private double numberB = 0;

    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 double getResult() throws Exception {
        double result = 0;
        return result;
    }
}

OperationFactory.java(管理对象的生成的工厂类)

package designpatterns.simplefactorymode.service;

/**
 * @author :DengSiYuan
 * @date :2018/12/2 12:19
 * @desc :工厂模式,程序的入口,动态创建符合类型的对象
 */
public class OperationFactory {

    public static Operation createOperation(String type){
        Operation operation = null;
        //判断类型,创建对象
        switch (type){
            case "+":
                operation = new OperationAdd();
                break;
            case "-":
                operation = new OperationSub();
                break;
            case "*":
                operation = new OperationMul();
                break;
            case "/":
                operation = new OperationDiv();
                break;
            default:
                System.out.println("输入有误!请检查后重新输入!");
        }
        return operation;
    }
}

OperationAdd.java(加法类)

package designpatterns.simplefactorymode.service;

/**
 * @author :DengSiYuan
 * @date :2018/12/2 11:37
 * @desc :加法运算
 */
public class OperationAdd extends Operation {

    @Override
    public double getResult(){
        double result = 0;
        result = getNumberA() + getNumberB();
        return result;
    }

}

Client.java(客户端)大家可以去实现更加通用的,用户输入运算式,判断符号(封装成一个方法)

package designpatterns.simplefactorymode.client;

import designpatterns.simplefactorymode.InputDeal;
import designpatterns.simplefactorymode.service.Operation;
import designpatterns.simplefactorymode.service.OperationFactory;

import java.util.Scanner;

/**
 * @author :DengSiYuan
 * @date :2018/12/2 12:27
 * @desc :用户端
 */
public class UserClient {
    public static void main(String[] args) throws Exception {
        String[] test = {"5","+","8"};
        String input = InputDeal.getEveryValue(test);
        Operation operation = OperationFactory.createOperation(input);
        operation.setNumberA(Integer.parseInt(test[0]));
        operation.setNumberB(Integer.parseInt(test[2]));
        System.out.println(operation.getResult());
    }
}

大家可以看到一个初级的使用简单工厂模式的计算器,根据一步一步的level比较,可以清楚的看到简单工厂模式存在的必要性以及他的优点。

持续更新设计模式!!