浅谈常用设计模式

一、设计原则

  1. 开闭原则
    释义:对扩展开放,对修改关闭
    理解:我们平常的业务一般会不断进行迭代,一般的做法是在原流程上直接改,“开闭原则”的目的通俗的说就是不在原流程上直接改,而是在第一次写原流程时就留一些“口子”,之后的迭代在这些口子中改。
    例子:卡券核销的流程,原流程是传入卡券和用户id然后核销,现在需要在核销之前判断用户如果在黑名单则禁止核销。原流程可以这样写

    public class Moshi1 {
    
        public void hexiao(String userid, String couponNo) {
            beforehexiao(userid);
            consume(couponNo);
        }
    
        // 核销之前
        public void beforehexiao(String userid) {
        }
    
        // 核销
        public void consume(String couponNo) {
           //核销业务
        }
    }
    

    beforehexiao()是为未来可能的迭代留的口子,之后可以继承重写beforehexiao()这个方法来实现黑名单验证。事实上,很少有人会像上面例子那样写代码,原因是大部分业务都是比较稳定的业务,很少有变化。
    总结:开闭原则就是不在原有的流程上修改,而是在最初设计的“口子”上做业务迭代

  2. 依赖倒置
    释义:依赖抽象而不是依赖具体对象
    理解:依赖常见的有聚合、方法依赖等;倒置是指抽象(接口和抽象类)和抽象的实现对象。依赖对象属于正置(对象才真正实现了功能),依赖抽象属于倒置
    例子:mvc中service依赖mybatis的mapper接口

  3. 单一职责
    释义:一个类只干“一件事“,实现类要单一
    理解:一件事,并不是只有一个方法,像卡券从领取、赠送,核销、删除虽然是四个方法,但都是处理卡券所以应该写在一个类里。
    总结:向我们平常写的controller,都会把相同的业务写在一起,方便寻找和修改

  4. 迪米特法则
    释义:不该知道的不要知道,一个类应该保持对其它对象最少的了解,降低耦合度
    理解:就是不直接依赖对象,感觉依赖倒置也是其中一种,另一种是在依赖对象间创建一个对象来间接依赖。 如下图2
    总结:无论是依赖抽象还是依赖间接对象,目的就是让依赖对象改变时不会影响被依赖对象

依赖
模块A
模块B
依赖
依赖
模块A
间接对象
模块B
  1. 里氏替换原则
    释义:不要破坏继承体系,子类重写方法功能发生改变,不应该影响父类方法的含义
    理解:抽象类和接口定义方法的功能,子类实现方法,但是不能跑破坏父类的定义。比如父类定义的是加法,可你实现却用乘法,这会带来灾难。

二、分类

  1. 按作用可以分为如下两类
    • 提升灵活性:让对象可以独立变化,不会影响其他对象
      这类设计模式有:代理模式、装饰模式、桥模式、组合模式、解释器、观察者、状态模式、命令模式、责任链、策略模式、模板方法、享元模式、备忘录、访问者
    • 降低复杂度:对象的方法或构造过程很复杂,通过另一个对象来屏蔽对外的复杂性。
      这类设计模式有:建造者模式、工厂、抽象工厂、外观、适配器模式、迭代器、中介者、原型模式、单例模式

三、结构相似的模式

  1. 依赖抽象
    桥模式、访问者、观察者、策略模式
    • 桥模式、观察者、策略模式一般是聚合依赖,访问者一般是方法依赖
    • 甚至可以说,桥模式是访问者、观察者、策略模式的基础。
    • 访问者主要用于对象集遍历;观察者主要用于与主流程无直接关联的流程调用;策略模式用于处理主流程中易变部分,是主流程的一部分。
  2. 通过间接对象处理构建
    工厂、抽象工厂、建造者
    • 工厂、抽象工厂构造的对象是固定的(属性),是编译时就可以确定的
    • 建造者构造对象是动态的,根据不同条件会有不同结果(属性)
  3. 继承的方式
    适配器、模板方法
    • 模板方法和策略模式的使用场景类似,区别是,他是用继承的方式处理主流程中易变部分
    • 适配器用于两个体系的连接,一个框架会通过适配器调用另一个框架
  4. 将目标和处理目标的方法封装在一起
    解释器、状态模式、命令模式
    • 解释器用于语法的解释,日常开发应该很难用到;
    • 状态模式,用于状态的处理,像订单会有很多种状态,每种状态都会有不同的处理,且状态间是有序的,相互关联的;
    • 命令模式,用于一些特定情景的处理,每个命令是相互独立的,没有关联的。
  5. 都会创建一个间接对象来包裹被调用对象
    装饰模式、代理模式、外观、中介者
    • 装饰模式,一般是增强原有的功能,会依赖原有功能;
    • 代理模式,并不依赖原有功能,一般是对原有功能进行访问控制拦截;
    • 外观,将原先复杂的调用细节抽取出来,提供一个简单的对外接口,像我们平时会把很长的方法一部分抽取到一个单独方法中,这就是一种外观模式;
    • 中介者,可以认为是外观的升级版,处理更复杂的调用关系。
  6. 多个有序对象组合在一起
    组合模式和责任链
    • 组合模式一般在构造上下级菜单时有所应用
    • 责任链,日常开发中很少应用

四、使用情景相似的模式

  1. 处理主流程中变化部分
    策略模式,模板方法
    • 策略模式,模板方法实现方式不同,前者用依赖,后者用继承
  2. 调用多个的对象
    观察者、责任链
    • 观察者是无序的,相互间没有影响的;责任链是有序的,相互间是有影响的,责任链就像流水线一样,前一个人的处理会影响的下一个人。
    • 观察者依赖其他流程,观察者随着其他流程的进行而进行;责任链不依赖其他流程。

五、常用的设计模式

  1. 桥模式
    这应该是最常见的了,mvc模型就是
  2. 代理模式
    spring aop,事务 使用的是动态代理,我们日常开发应该很少用
  3. 命令模式
    使用java8 的话可能会常用,比如这种Map ,把目标和处理目标的方法封装在一起(map中)
  4. 责任链
    servlet 过滤器,spring拦截器
  5. 访问者
    sax 方式xml遍历
  6. 工厂
    spring工厂
  7. 外观
    这个也很常见,像将一个长方法部分抽取到几个方法中就是。
  8. 迭代器
    集合的迭代器
  9. 原型模式、单例模式
    spring 的
  10. 策略模式、模板方法
    这两个如果稍微的思考和设计一下我们的代码,能应用的地方应该很多

六、总结

23种设计模式是对遵循了设计原则的好的代码的总结,并不需要刻板的照搬结构,只要你遵循了设计原则,很可能会写出第24种设计模式。

你可能感兴趣的:(java,设计模式,java)