编程中的23种设计模式

编程中的23种设计模式

王争《设计模式之美》专栏学习笔记

设计模式要干的事情就是解耦。创建型模式是将创建和使用代码解耦,结构型模式是将不同功能代码解耦,行为型模式是将不同的行为代码解耦。

设计模式在于设计的意图,也就是应用场景。如果单纯看设计思路或者代码实现,一些模式是比较相似的,比如策略模式和工厂模式。

借助设计模式,我们利用更好的代码结构,将一大坨代码拆分成职责更单一的小类,让其满足开闭原则,高内聚低耦合等特性,从此来控制和应对代码的复杂性,提供代码的可扩展性。

创建型模式

解决对象的创建问题

  • 单例模式
  • 工厂模式
  • 建造者模式
  • 原型模式

结构性模式

类或对象的组合或组装

  • 代理模式
    • 增强原始类无关的功能
    • 常用于:监控、统计、鉴权、限流、事务、幂等、日志、RPC、缓存等
  • 桥接模式
    • “抽象”和“实现”独立开发,通过对象之间的组合关系,组装在一起。
    • 应用1:JDBC驱动(JDBC和Driver独立开发,组合在一起)
    • 应用2:API监控告警,通知渠道:邮件、短信、微信、自动语音电话;紧急程度:严重、紧急、普通、无关要紧;不同的紧急程度对应不同的通知渠道
  • 装饰器模式
    • 增强原始类相关的方法(所以需要继承同样的父类或者实现同样的接口),能嵌套多个装饰器
    • 应用1:Java IO 流
    • 应用2:增加缓存
  • 适配器模式
    • “补救策略”,提供跟原始类不同的接口。代理模式和装饰器模式提供的都是跟原始类相同的接口。
    • 应用:
      • 封装有缺陷的接口设计
      • 统一多个类的接口设计
      • 替换依赖的外部系统
      • 兼容老版本接口
      • 适配不同的数据格式
  • 门面模式
    • 解决的是接口易用性、性能、事务问题,而适配器解决的是原接口和目标接口不适配的兼容性问题。
    • 应用:子系统(或App)需要调用多个接口的情况;用户和钱包两个领域的分布式事务问题。
  • 组合模式
    • 应用:文件系统目录结构
  • 享元模式
    • 目的是共享使用对象,达到复用目的(通过一个List或Map缓存已经创建好的享元对象)
    • 应用1:棋牌模式、文本编辑器
    • 应用2:Java Integer(-127~127利用享元模式提前创建好)、String 利用享元模式复用字符串常量。

行为型模式

类或对象之间的交互

  • 观察者模式
    • 也称为发布订阅模式,是一对多的关系。将观察者和被观察者代码解耦。
    • 应用1:RSS Feeds,邮件订阅
    • 应用2:进程内有同步阻塞或异步非阻塞实现方式,异步非阻塞如EventBus;跨进程的观察者模式如RPC接口调用,消息队列MQ
    • 生产者>消费者的区别:
      • 生产者和消费者是以异步实现,多对多,并且消费者存在竞争关系,一条消息只能被一个消费者消费。
      • 发布订阅则可以同步也可以异步方式实现,一对多,一条消息可以被多个订阅者消费,订阅者没有竞争关系,发布和订阅两者也在流程上存在先后关系
  • 模板模式
    • 模板方法和回调应用场景是一致的,都是定义好算法骨架,并对外开放扩展点,符合开闭原则;两者的却别是代码的实现上不同,模板方法是通过继承来实现,是自己调用自己回调是类之间的组合。
    • 应用:JdbcTemplate、RedisTemplate、RestTemplate
  • 策略模式
    • 解耦策略的定义、创建、使用,控制代码复杂度,让每个部分都不至于过复杂,代码行数过多。移除 if-else 和 switch-case 分支逻辑判断(策略工厂),保证代码的可维护性,和遵循KISS原则。
    • 应用:对一个文件进行排序。文件中只有整数,并且相邻的数字通过逗号区隔。文件的大小可能:10GB(外部排序)、100GB(多线程外部排序)、 1TB(多机MapReduce)。
  • 职责链模式
    • 将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。
    • 应用:敏感词过滤、Servlet Filter、Spring Interceptor
  • 状态模式
    • 又叫有限状态机,有3个部分组成:状态、事件、动作。其中,事件也称为转移条件。事件触发转态的转移和动作的执行。动作可以不是必须的。状态机的三种实现方式:分支逻辑法、查表法、状态模式。
    • 应用:游戏、工作流引擎
  • 迭代器模式
    • 数组遍历器,在编程语言中已经提供为一种类库来使用
    • 应用:1、遍历集合的同时不要增删元素;2、设计一个支持快照功能的iterator
  • 访问者模式
    • 允许一个或多个操作应用到一组对象上,解耦操作和对象本身。双分派语言(Double Dispatch)不需要支持访问者模式
    • 应用:批量处理PDF、PPT、Word文件,提取内容放到 txt 文件中。定义访问者类(Extractor、Compressor),将对象和操作解耦,将业务操作抽离出来,使得符合开闭原则。
  • 备忘录模式
    • 也叫快照模式,在不违背封装原则的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,一遍之后方便恢复对象为先前状态。
    • 应用:防丢失、撤销、恢复等。通过全量备份和增量备份结合的方式(低频全量备份,高频增量备份),减少存储和时间的消耗。
  • 命令模式
    • 命令模式将请求(命令)封装为一个对象,这样可以使用不同的请求参数化其他对象(将不同请求依赖注入到其他对象),并且能够支持请求(命令)的排队执行、记录日志、撤销等(附加控制)功能。
    • 应用:用来控制命令的执行,比如:异步、延迟、排队执行命令、存储命令、给命令记录日志等。
  • 解释器模式
    • 解释器模式为某个语言定义它的语法(或者叫文法)表示,并定义一个解释器来处理这个语法。
    • 应用:1、告警规则,如触发条件:key1 > 100 && key2 < 1000 || key3 == 200;2、计算表达式等,如 8 3 2 4 - + *
  • 中介模式
    • 中介模式的设计思想跟中间层很像,通过引入中介这个中间层,将一组对象之间的交互关系(或者依赖关系)从多对多(网状关系)转换为一对多(星状关系)。原来一个对象要跟 n 个对象交互,现在只需要跟一个中介对象交互,从而最小化对象之间的交互关系,降低了代码的复杂度,提高了代码的可读性和可维护性。
    • 应用:UI交互,如注册用户页面,切换用户登录和用户注册的UI,显示不同输入框等。
    • 与观察者模式的区别:中介模式一般可以控制参与者的执行顺序,而观察者一般控制不了。

总结

熟悉23种设计模式的原理、实现、设计意图和应用场景。避免过度设计,避免设计不足。设计的初衷是提高代码质量,不要脱离具体的场景去谈设计。

设计模式


本人自动发布于:https://github.com/giscafer/blog/issues/59

相关文章