大话设计模式笔记(一)の简单工厂模式

概要

  • 一个好的程序猿/媛敲出来的代码应该是可维护、可复用、可扩展的,也就是具有较好的灵活性。
  • 为了达到以上目的,在还没敲代码之前,需要事先考虑通过何种方式能够使自己的程序的耦合度降低,最基本的便是面向对象的封装、继承、多态
  • 但这往往是不够的,需要根据实际情况选择合适的设计模式使得程序变得更加灵活,容易修改,并且易于复用
  • 复用并不是复制的意思。在实际开发当中,有时候会遇到一些类似的功能,有一部分已经是在别的 Service 中实现了(整个方法的功能是不一样的),但可能出于项目赶进度的时候,也可能做这个功能的员工水平不足,于是乎直接将此处代码一顿操作 ctrl + C / V 一切搞定。但对日后维护的人来说是一场灾难,万一又是自己,日后少不了“早知如此,何必当初”的感叹了。养成好的编码习惯很重要。
  • 话说得好听谁都会,正是因为人都有成长的过程,所以对业务的理解转化为程序,以及编写代码的优美程度也是一步一个脚印走出来的。是否能够做到真正的松耦合,又或者“松”的过度导致程序过于臃肿,都跟个人的层次有关。付出不一定有收获,但不付出,肯定没有收获。

抛砖引玉

案例

实现一个简单计算器代码(加减乘除)

普通实现方式

/**
 * 运算类
 * Created by callmeDevil on 2019/5/26.
 */
public class Operation {

    /**
     * 获取运算结果
     * @param numA 数值A
     * @param numB 数值B
     * @param operate 运算符
     * @return
     */
    public static double getResult(double numA, double numB, String operate) {
        double result = 0L;
        switch (operate) {
            case "+":
                result = numA + numB;
                break;
            case "-":
                result = numA - numB;
                break;
            case "*":
                result = numA * numB;
                break;
            case "/":
                result = numA / numB;
                break;
            default:
                break;
        }
        return result;
    }

}
/**
 * 测试类
 * Created by callmeDevil on 2019/5/26.
 */
public class Test {

    public static void main(String[] args) {
        Operation operation = new Operation();
        double numA = 10;
        double numB = 2;
        System.out.println("加法:" + operation.getResult(numA, numB, "+"));
        System.out.println("减法:" + operation.getResult(numA, numB, "-"));
        System.out.println("乘法:" + operation.getResult(numA, numB, "*"));
        System.out.println("除法:" + operation.getResult(numA, numB, "/"));
    }

}

但是这样就有个问题,如果这个计算器还需要实现开根号运算呢?难道就直接在Operation类添加一个switch分支就行了吗?不是的,这样会让原来良好运行的代码产生变化,风险太大,因此需要将各种运算的逻辑分离开来,此处引入简单工厂模式

简单工厂模式实现

定义

又称为静态工厂模式,根据工厂类传入的参数动态决定创建某种类(这些类都继承自同一父类或实现同一接口)的实例。

UML图

结合代码有注释

/**
 * 运算基础类
 * Created by callmeDevil on 2019/5/26.
 */
public class BaseOperation {

    private double numA;
    private double numB;

    // 此处省略get、set方法

    /**
     * 获取结果
     * @return
     */
    public double getResult() {
        double result = 0L;
        return result;
    }

}

/**
 * 加法运算
 * Created by callmeDevil on 2019/5/26.
 */
public class OperationAdd extends BaseOperation {

    @Override
    public double getResult() {
        return getNumA() + getNumB();
    }

}
/**
 * 减法运算
 * Created by callmeDevil on 2019/5/26.
 */
public class OperationSub extends BaseOperation {

    @Override
    public double getResult() {
        return getNumA() - getNumB();
    }

}
/**
 * 乘法运算
 * Created by callmeDevil on 2019/5/26.
 */
public class OperationMul extends BaseOperation {

    @Override
    public double getResult() {
        return getNumA() * getNumB();
    }

}
/**
 * 除法运算
 * Created by callmeDevil on 2019/5/26.
 */
public class OperationDiv extends BaseOperation {

    @Override
    public double getResult() {
        if (getNumB() == 0){
            throw new RuntimeException("除数不能为0!");
        }
        return getNumA() / getNumB();
    }

}
/**
 * 测试类
 * Created by callmeDevil on 2019/5/26.
 */
public class Test {

    public static void main(String[] args) {
        // 实现其他运算只需要更改输入的运算符即可
        BaseOperation operation = OperationFactory.createOperation("+");
        operation.setNumA(10);
        operation.setNumB(2);
        System.out.println("加法:" + operation.getResult());
    }

}

相比普通实现方式的好处

将每种运算的具体实现分离在不同的类中,工厂类只需要负责根据输入的运算符来创建对应的运算类实例即可。比如要一个开方运算是吧,那么需要创建一个开方运算类,同样继承BaseOperation,接着在工厂类中switch中添加一个case分支,然后客户端便能够跟其他运算一样调用。
可能有人会问,这里不也同样是修改了switch分支条件吗?有什么区别?问得好,说明有思考过,但是原因也很明显,要仔细想想。把四种基础运算具体实现分离出去,工厂类中就包含了四行创建实例的代码,这时修改了switch分支的风险,和普通实现方式的风险相比,哪个大已经不用细说了吧。

总结

这里案例代码比较简单,所以看起来会非常明朗,想必不必多说读者应该也能稍有体会。假如每个类型的运算非常复杂,甚至与其他模块关联,那使用设计模式的好处就体现出来了,比起全部代码堆在一个switch case上,在单独的一个类里面会更好维护和扩展吧?想做到完全不修改switch的代码是不可能,最重要的是我们达到了松耦合、可复用、可扩展目的,同时还降低了风险,有何不可。

(0)

相关推荐

  • 大话设计模式笔记(二)の策略模式

    举个栗子 问题描述 商场收银软件,营业员根据客户所购买的商品单价和数量,向客户收费. 简单实现 /** * 普通实现 * Created by callmeDevil on 2019/6/1. */ ...

  • 【从零学习OpenCV 4】Mat类支持的运算

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<从零学习OpenCV 4>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...

  • 设计模式学习笔记 ———— 简单工厂模式

    # 背景 简单工厂模式是很多程序员学习的第一个设计模式,因为其不但原理简单而且易于上手,在日常工作的代码中也常有体现.今天分享一个基于实现"加"."减".&qu ...

  • 大神可以解释一下c语言里int,double,c,d,IF都是什么意思、在什么情况下用吗?

    我本人用C,C++比较多,回答一下你的提问. 首先,分一下类.int,double,这两个在c语言中表示变量类型:c,d,不能单独使用,与%一起,表示格式化输出的数据类型:至于IF,它不属于C语言的关 ...

  • Numb │ 每日糊图:20170721

    每日糊图 No.15399 Numb 活在别人眼里再风光也只是酷暑般的煎熬, 只有做一个真正自己才能沐浴冬日的暖阳. However successful to be a person in othe ...

  • 详解lua的string与hex数据(十六进制)

    本文希望阐述的问题 在lua中处理 string 与 hex(十六进制数) 的思维转换 背景 luat在处理通信的时候,总会设计到数据处理,例如: socket:sendsocket:recvspi. ...

  • 深入学习《大话设计模式》 简单工厂模式

    简单工厂模式 定义:封装改变,既然要封装改变,自然也就要找到需要更改的代码,然后将需要更改的代码用类来封装,这样的思路就是我们简单工厂模式的实现方式了 下面我们通过一则小故事来简述一下我们在项目中为什 ...

  • 大话设计模式笔记(六)の工厂方法模式

    栗子回顾 简单工厂模式: https://www.cnblogs.com/call-me-devil/p/10926633.html 运算类使用工厂方法模式实现 UML图 代码实现 工厂接口 /** ...

  • PHP设计模式之简单工厂模式

    PHP设计模式之简单工厂模式 先从简单工厂入门,不管是面试还是被他人面试,在问到设计模式的时候,大多数人都会提到工厂模式.毫无疑问,工厂相关的几种模式在设计模式中是最出名的也是应用比较广泛的一种模式. ...

  • [PHP小课堂]PHP设计模式之简单工厂模式

    PHP设计模式之工厂方法模式 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[DarkMatterZyCoder/149844827]免费得PHP.项目管理学习资料

  • 【C++设计模式一】C++简单工厂模式

    (1)定义 定义一个简单工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类. (2)结构 简单工厂模式有以下的结构: 工厂(Factory):根据客户提供的具体产品类的参数 ...

  • 【重温设计模式】之002简单工厂模式

    [重温设计模式系列源码] 简单工厂模式 基本原理 含义 简单工厂模式又叫静态方法模式(因为工厂类定义了一个静态方法). 在现实生活中,工厂是生产产品的, 同样的,在设计模式中,一个负责生产" ...

  • 【设计模式】简单工厂模式

    定义 通过工厂类提供的方法,创建不同的派生类 通常创建的类都具有共同的基类/接口 优缺点 优点 客户端与具体的实现类解耦 缺点 新增产品需要修改原来工厂类的方法,不符合开闭原则 角色 客户端 --&g ...

  • PHP设计模式—工厂模式之简单工厂模式

    定义: 简单工厂模式:将调用者和创建者分离,实现解耦,调用者直接向工厂请求,通过工厂去选择需要实例化的对象,用一个单独的类来做这个创建实例的过程. 代码实例: 问题:假设一个关于个人事务管理的项目中有 ...