1. 业务场景讲解设计模式(简单工厂模式)

现阶段我之所以再次学习设计模式,是因为感受到企业项目的多层封装与调用的复杂性,既然这样那肯定是有自己的设计道理的,能让系统更具有拓展性,安全性,易维护性。所以,我希望这次站在领导设计者的角度去实现功能,而不是简单的增删改查。

1 实现一个计算器

现在我们什么都不考虑,仅仅使用Java实现一个计算器

/**
 * 简单实现计算器
 * 设计:依次输入数字A,运算符号,数字B
 */
public class calculator {
    public static void main(String[] args) {

        System.out.println("请输入数字A:");
        Scanner strNumberA = new Scanner(System.in);
        Double numberA = strNumberA.nextDouble();

        System.out.println("请选择运算符:+ - * /");
        Scanner strOperate = new Scanner(System.in);
        String operate = strOperate.next();

        System.out.println("请输入数字B:");
        Scanner strNumberB = new Scanner(System.in);
        double numberB = strNumberA.nextDouble();

        //计算
        switch(operate){
            case "+":
                System.out.println(numberA + numberB);
                break;
            case "-":
                System.out.println(numberA - numberB);
                break;
            case "*":
                System.out.println(numberA * numberB);
                break;
            case "/":
                System.out.println(numberA / numberB);
                break;

        }

    }
}

简单测试一下
在这里插入图片描述

2 初步解耦代码

现在我的需求变了,我觉得这个代码中算法和页面混在一起很臃肿。若我需要调整数据展示的样式,就会被看到全部的代码,也不安全。因此我本能的希望可以将这两部分隔开。
那现在就成了这样,一部分负责算法,一部分负责展示。


/**
 * 计算部分
 */

public class calculator01 {
    public void getOpertion(double numberA,double numberB,String operate){
        //计算
        switch(operate){
            case "+":
                System.out.println(numberA + numberB);
                break;
            case "-":
                System.out.println(numberA - numberB);
                break;
            case "*":
                System.out.println(numberA * numberB);
                break;
            case "/":
                System.out.println(numberA / numberB);
                break;

        }
    }


}


public class client {
    public static void main(String[] args) {

        System.out.println("请输入数字A:");
        Scanner strNumberA = new Scanner(System.in);
        Double numberA = strNumberA.nextDouble();

        System.out.println("请选择运算符:+ - * /");
        Scanner strOperate = new Scanner(System.in);
        String operate = strOperate.next();

        System.out.println("请输入数字B:");
        Scanner strNumberB = new Scanner(System.in);
        double numberB = strNumberB.nextDouble();

        calculator01 calculator01 = new calculator01();
        calculator01.getOpertion(numberA, numberB, operate);
    }
}

3 深度解耦代码

我现在又又有需求了,我希望增加一个开根运算,你会怎么做呢?
是不是在算法类中,switch添加一个开根运算。
不错,但是这样我觉得还是有问题,就是我只让你增加一个开根运算,你就看到了我的其他算法实现(加减乘除),如果你将我的加法修改为减法,这对我也就太不安全了。所以我希望可以将每个算法都隔离开。

那怎么隔离呢?
先观察这些算法的实现,发现有共同点,就是都会传入两个参数。根据面向对象习惯,我打算提取出公共属性。例如,需要加法,我就创建一个名为加法的子类,继承运算类。
在这里插入图片描述

/**
 * 计算器的公共类:定义参数A,B,和运算结果
 */
public abstract 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 get_NumberB() {
        return numberB;
    }

    public void setNumberB(double numberB) {
        this.numberB = numberB;
    }

    abstract double getResult();

}

/**
 * 加法类
 */
public class operationAdd extends Operation{
    @Override
    double getResult() {
        double result = 0;
        result = getNumberA() + get_NumberB();
        return result;
    }
}

/**
 * 减法类
 */
public class operationSub extends Operation{
    @Override
    double getResult() {
        double result = 0;
        result = getNumberA() - get_NumberB();
        return result;
    }
}

/**
 * 乘法类
 */
public class operationMul extends Operation{
    @Override
    double getResult() {
        double result = 0;
        result = getNumberA() * get_NumberB();
        return result;
    }
}
/**
 * 除法类
 */
public class operationDev extends Operation{
    @Override
    double getResult() {
        double result = 0;
        //除数不等于0
        if(get_NumberB()!= 0){
            result = getNumberA() / get_NumberB();
        }
        return result;
    }
}

不错,现在每种算法算法之间都做到了相互隔离,如果我们需要添加一个开根运算,只需要再添加一个类就可以了,这样系统的拓展性就很好。

此刻有一个新的问题,就是我如何调用呢,我如何让计算器知道我使用了哪种算法。
最简单粗暴的方式就是在客户端代码中,写一个switch判断传入的运算符号,创建对应的算法类对象。
可是这样一来,算法类不就又和界面展示混合了,干了半天白费功夫。所以我们希望将创建对应算法类对象的代码单独分离出去。
例如我们希望做减法,那么就传入这个类内部就会调用创建减法类的对象。
这种专门负责创建实例对象的家伙,就跟加工厂一样,因此就提出了简单工厂设计模式的概念。
在这里插入图片描述
下面看看代码感受一下吧

public class OperationFactory {
    public static Operation creatOperate(String operate){
        Operation oper = null;
        switch(operate){
            case "+":
                oper = new operationAdd();
                break;
            case "-":
                oper = new operationSub();
                 break;
            case "*":
                oper = new operationMul();
                break;
            case "/":
                oper = new operationDev();
                break;
            }
        return oper;
    }
}

public class client {
    public static void main(String[] args) {

        System.out.println("请输入数字A:");
        Scanner strNumberA = new Scanner(System.in);
        Double numberA = strNumberA.nextDouble();

        System.out.println("请输入数字B:");
        Scanner strNumberB = new Scanner(System.in);
        double numberB = strNumberB.nextDouble();


        System.out.println("请选择运算符:+ - * /");
        Scanner strOperate = new Scanner(System.in);
        String operate = strOperate.next();

        Operation operation = OperationFactory.creatOperate(operate);
        operation.setNumberA(numberA);
        operation.setNumberB(numberB);

        double result = operation.getResult();
        System.out.println(result);


    }
}

4 总结很重要

在上述案例中,我们将最开始的一坨代码按照需求,一步步优化解耦(专业名词叫:重构代码),最终分成了多个类。可以发现,最终的代码具有了很好的拓展性和可维护性。在案例中,我们是什么使用了工厂模式呢?是我们依据需求,将算法拆分到最后才考虑到的,并不是生硬的告诉大家直接使用工厂模式。希望大家可以真切的感受到设计模式的魅力。
这只是最初级的一个案例,下一章我们将介绍一个更有特色的案例,更贴近生活。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值