设计模式杂谈

669 阅读9分钟

前言

设计模式地本质就是找到变化,封装变化。为了做到这个,引出了很多设计原则,例如单一原则、简单原则、最少原则、表达原则、职责原则、面向对象原则、反转原则、惯例原则、分离原则、契约原则,当然也有一些思维,例如组合思维、分层思维、工程思维、对象思维、迭代思维等。

目录

一、六大设计模式准则

  • 单一职责
    • 类的职责应该单一,一个方法只做一件事,每次改动到最小单位的方法或类,尽量只有一个原因引起变化
  • 里氏替换原则
    • 所有引用基类的地方,必须能够使用其子类直接替换
    • 子类继承父类,重写方法
    • 覆盖父类方法时,输出可以缩小,输入可以放大
  • 依赖倒置
    • 高层模块不能依赖底层模块,两者应该依赖其抽象
    • 抽象针对Java就是抽象类、接口,细节就是实现类,细节应该依赖抽象。面向接口,面向抽象编程,可以减少类之间的耦合性,提高稳定性。
  • 接口隔离原则
    • 客户端不应该依赖它不需要的接口,一个接口尽量只服务于一个子模块或业务逻辑
    • 接口需要高内聚,减少对外交互
    • 设计需要有限度,设计粒度越小,越灵活,但是结构会很复杂。
  • 迪米特法则
    • 最少知识原则,一个对象应该对其他对象有最少的了解,对类的低耦合提出了明确的要求
  • 开闭原则
    • 对扩展开放,对修改关闭
    • 抽象元素,封装变化

二、设计模式类型

  • 创建型设计模式

    • 关注重点在于一个对象内部结构的,常常是接口与实现的组合
  • 结构型设计模式

    • 关注重点就在于多个对象之间的组合方式
  • 行为型设计模式

    • 关注点是对象内部算法及对象之间的职责和分配,比如,具体实现算法、选择策略、状态变化等抽象概念。

    • 行为型模式还可以分为以下两种。

      • 类行为型模式:使用继承的方式来关联不同类之间的行为。

      • 对象行为型模式:使用组合或聚合方式来分配不同类之间的行为。

三、设计模式

1、创建型模式

单例模式

很常见,就是强制实现对象唯一创建,伴随者常见的单例线程安全等问题

建造者模式

即Builder模式,侧重点在于如何实现对象创建过程中的组合,针对参数很多的情况下,我们会考虑用Builder模式,然后在最后build时,创建一个对象,实现了对象创建过程的多态。

抽象工厂模式

侧重点是创建一组实现统一抽象产品的工厂对象族,本质上是为了寻找正确的抽象产品,保证被创建对象的工厂之间的一致性

工厂方法模式

将创建对象的时机延迟到了每一个具体的工厂中,让具体工厂解决复杂对象创建的过程,并定义接口,来保证创建对象时的可任意替换行,实现了对象创建时的多态

原型模式

通过复制,快速建立对象副本,可以动态扩展运行时的对象能力,实现了对象拷贝的多态

2、结构型模式

适配器模式

  • 实现了不同接口功能间的转换,将源角色转换成目标角色

桥接模式

  • 抽象和实现分离。实现了抽象实体和抽象行为之间的永久绑定,可以理解为在基于已有的构件上设计可能会发生变化的行为

组合模式

  • 于表达整体和部分的关系,可以忽略单个对象和合成对象之间的差别。它实际采用的是一种树状结构,叶子节点、组合节点

装饰模式

  • 动态地给一个对象添加一些额外的职责,与继承不同,通过代理方式实现了接口功能的多态,避免了大量子类的派生。它适用于链状和树状的结构,但容易造成对象与装饰器之间耦合度过高。

门面模式

  • 用于对子系统提供统一的接口,与中介模式不同,侧重点是提供给外部一个访问接口,除了这个接口不允许有任何访问子系统的行为发生

享元模式

  • 用于解决大对象重复创建损耗资源的问题,通过共享对象池来复用对象

代理模式

  • 模式的结构与装饰模式非常相似,但侧重点不同,一种是修改对象的行为,另一种是控制访问。

3、行为型模式

访问者模式

  • 在对象级别中实际为树型结构,与抽象工厂模式类似。它给使用者提供了一种统一访问树结构中数据节点的方式,因此具备灵活扩展的特性

模板方法模式

  • 定义一个算法模板,并将具体的执行步骤延迟到子类中实现

策略模式

  • 将多个不同的算法封装成策略,让它们可以互相替换,适合应用于对计算效率有一定要求的系统。策略模式通常会和工厂方法模式配合使用,为使用者提供一组使用策略

状态模式

  • 最常用的实现方式是状态机,大量应用于需要控制状态流转的系统中。常用在游戏、工作流引擎、购物流程等系统开发中

观察者模式

  • 观察者模式侧重于将观察者和被观察者代码解耦,而中介者则侧重于充当两个对象之间的新媒介

备忘录模式

  • 也叫快照模式,通常用于捕获一个对象的内部状态,比如保存、打开、关闭等状态,并在执行对象之外保存一个副本状态,方便用于之后恢复对象到某一个时间状态

中介者模式

  • 最大的作用在于解耦对象之间的直接引用,设计思想和分层思想很像,通过引入一个中间层,将层与层之间的多对多关系变为一对多关系

迭代器模式

  • 大量应用于基础类库中,对重复遍历操作进行封装。现在大部分编程语言都提供了现成的迭代器可以使用

解释器模式

  • 为某个语言(编程语言也是语言)定义它的语法表示,比如 if-else 语法、正则,并定义一个解释器用来处理这个语法

命令模式

  • 将某个命令(函数方法)封装成对象进行传递,关注的维度是命令,比如,打开、关闭文件的命令。用于处理多个命令调用和使用远程服务的场景

责任链模式

  • 动态指定职责的承担对象,由各自对象实现对应职责

四、设计模式比对

1、创建类模式

工厂方法模式和建造者模式

工厂方法模式注重点是整体对象的创建方法,而建造者模式注重点是部件对象构建的过程,目的是通过一步一步精确构造创建出一个复杂的对象。

例如,制造一辆车,通过工厂方法,直接生产出来的就是一辆可以开的车,而通过建造者模式,需要一步一步组装,组装好一辆车后才生成。

抽象工厂模式和建造者模式

抽象工厂模式实现对产品家族的创建,一个产品家族是这样的一系列产品:具有不同分类维度的产品组合,不需要关心构建过程,只关心什么产品由什么工厂生产即可。而建造者模式依旧是需要按指定流程创建产品,组装新产品。

2、结构类模式

代理模式和装饰者模式

两者的相同点就是都具有相同的接口,不同点在于代理模式侧重于对代理过程的控制,而装饰模式则是对类功能进行加强或减弱,侧重于类功能的变化。

装饰者模式和适配器模式

两者都是包装作用,通过类委托的形式实现其功能。装饰者模式包装的是自己的兄弟类,属于同一个接口或父类,适配器模式则是作用于两个没有关系的角色之间的转换,将非本家族的对象伪装成家族对象,本质是非相同接口的对象。

3、行为类模式

命令模式和策略模式

策略模式的侧重点在于封装算法,认为算法是一个完整的、不可拆分的原子业务,目的是算法间可以独立、并可以相互替换。而命令模式则是对动作的解耦,把一个动作的执行分为执行对象(命令接收者,最终命令的具体执行过程)、执行行为(每个命令角色Command),让两者相互独立而不影响。

策略模式和状态模式

策略模式的侧重点在于封装算法,算法之间没有交互,算法可以自由切换。而状态模式封装的是状态,以达到状态切换,行为随着发生改变的目的。

观察者模式和责任链模式

在观察者模式中,一个具体的角色,它即可以是观察者,也可以是被观察者。这两种模式对于事务的处理都会产生触发链,即业务的处理流转,链条化处理,只不过是消息的分销渠道不同,上下节点的关系也不同(责任链中都不存在上下节点关系,而责任链上下节点关系很明确)

4、其它模式间对比

策略模式和桥接模式

桥接模式关注的是抽象和实现分离,实现抽象和实现都可以独立扩展,只要继承了抽象类就可以继续扩展。

门面模式和中介者模式

门面模式侧重于为复杂的子系统提供一个统一的访问入口,定义的是一个高层接口,可以避免外部模块深入到子系统内部,与内部细节耦合。中介者模式则是用一个中介对象来封装一系列同事对象的交互行为,使各对象之间不再显示地引用。