总结-23种设计模式

前言

设计模式——可以重复利用的解决方案

终于把23种设计模式看了一遍,现在总结一次,并加上自己的白话文理解与现实中使用过的场景,以便记忆。

六大原则

  1. 开闭原则
  2. 里氏替换原则
  3. 依赖倒置原则
  4. 单一职责原则
  5. 迪米特法则(最少知道原则)
  6. 接口分离原则

开闭原则是最基本的原则,里氏替换原则、依赖倒置原则是开闭原则的实现,结合6个原则看,我们在编程中最好都是抽象,低耦合,细微粒度。

模式分类

1. 创建型

主要用于描述如何创建对象。将模块中对象的创建和对象的使用分离。外界只需要知道接口,不需要知道具体的实现细节,符合单一职责原则

  1. 简单工厂模式

    定义一个工厂类负责管理创建其他类的实例,根据创建方法的参数返回不同类的实例。被创建的实例通常具有共同的父类。

    比如在工厂方法中写swicth,匹配拿到某个产品实例。

  2. 工厂方法模式

    不同的工厂子类创建不同的产品对象。比如再定义几个产品工厂,不同的产品工厂生产对应的产品。

  3. 抽象工厂模式

    提供一个创建一系列相关或相互依赖对象的接口。

    比如在工厂方法的基础上,又定义几个依赖产品的工厂,不同的依赖产品工厂生产不同的依赖产品。如果一个工厂需要生产不同的产品,应该选用抽象工厂模式而不是工厂模式,工厂模式适合生产一种产品的情况。

  4. 单例模式

    一个类只有一个实例,并且提供一个全局访问点。比如我们的登录框,点击后只能弹出一个。

  5. 生成器模式

    又叫创建者模式/建筑模式,构建复杂的对象模式,把对象的构建与表现分离,使得同样的构建过程可以创建不同的表示。

    比如在一个类中定义多个对象的组成部分,定义一个导向类根据不同需求组装对象。

  6. 原型模式

    根据原对象复印一个新对象,并根据需求对新对象进行微调。在JS原型链的领域上,经常会引申出:实现继承的五种方法

2. 结构型

主要用于描述如何实现类或对象的组合。

  • 类结构型模式关心类的组合:由多个类组合成一个更大的系统,一般只存在继承关系和实现关系
  • 对象结构型关心类与对象的组合:通过关联关系使得在一个类中定义另一个类的实例对象,然后通过该对象调用其方法。 根据“合成复用原则”,在系统中尽量使用关联关系来替代继 承关系,因此大部分结构型模式都是对象结构型模式。
  1. 外观模式

    又叫门面模式,定义了一个高层接口,为子系统中的一组接口提供一个统一的接口。

    比如做兼容的时候,把各种浏览器、移动端判断处理封装在一个文件,然后暴露出主接口,之后直接调用主接口就ok。

  2. 适配器模式

    又叫包装器模式,将一个接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

    原来我们平时修改参数(后端返回的参数不是我们想要的样子,把它们整成自己想要的样子)就是适配器模式。。但适配器模式本质上是一个亡羊补牢的模式,它解决的是现存的两个接口之间不兼容的问题,不应该在软件的初期开发阶段使用该模式;尽量在设计之初就规划好接口的一致性。

  3. 桥接模式

    将抽象部分与它的实现部分分离,使他们都可以独立地变化。

    桥接模式可以让我们提取多个底层功能模块,再拼装,在动画上用的就很多,比如设置走路模块,跑步模块,跳跃模块...人物需要时再拼装。

  4. 代理模式

    为某个对象提供一个代理,并由这个代理对象控制对原有对象的访问。相当于房产中介,es6里面的proxy也可以实现。

  5. 装饰者模式

    不改变原有对象的前提下,动态地给一个对象增加一些额外的功能。可以试着在vue装babel,搭es7环境,使用@decorator写装饰器,非常方便~

  6. 享元模式

    运用共享技术复用大量细粒度的对象。

    之前那些复用的功能函数,似乎就是这个模式,在网上发现利用这个模式,能够实现一个叫通用对象池的东西,这个类管理一个装载空闲对象的数组,如果外部需要一个对象,直接从对象池中获取,而不是通过new操作。

3. 行为型

主要用于描述类或对象怎样交互及怎样分配职责

  1. 职责链模式

    避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

    express 就使用了责任链模式,避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止,无论是作用域链、原型链、express、还是DOM节点中的事件冒泡,都能从中找到职责链的影子。但是有可能请求没有被正确处理或者进入死循环

  2. 命令模式

    将一个请求封装成一个对象,从而让我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。

    业务出现了 (回退操作)(重做操作)的需求的时候,就可以考虑使用这个模式。和之前代理模式中的举例有些相似,不过命令模式的本质是对命令进行封装,将发出命令的责任和执行命令的责任分割开。例如遥控器是一个调用者,不同按钮代表不同的命令,而电视是接收者。

  3. 解释器模式

    定义一个语言(使用规定格式和语法的代码)的文法,并且建立一个解释器来解释该语言钟的句子。我们的编译器,在对代码进行编译的时候也用到了该模式。就是对一条指令进行翻译,比如 up 5,需要写up做的事情,5代表啥。

  4. 迭代器模式

    又叫游标(Cursor),提供一个方法来访问聚合对象,而不用暴露这个对象的内部表示。

    迭代器模式,在我们的各种循环很常见,比如 each等,只要被迭代的聚合对象拥有length属性而且可以用下标访问,那么它就是迭代器。Javascript中的类数组对象也是迭代器。

  5. 中介者模式

    又叫调停者模式,用一个中介对象(中介者)来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。它与外观模式,代理模式有点像。可以在下面的链接看看他们的区别。

  6. 备忘录模式

    又叫 Token,在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。

    也可以看成缓存器,可以利用它进行撤销操作,还可以利用该模式做分页:点击下一页获取新的数据,点击上一页时又重新获取数据,会造成流量浪费,这时可以对数据进行缓存

  7. 观察者模式

    又叫 发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者模式(Dependents)。定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。

    vue发布订阅模式

  8. 状态模式

    又叫 状态对象,允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。常使用switch判断应用某个状态。

  9. 策略模式

    又叫 政策模式,定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换,策略模式让算法独立于使用它的客户而变化。

    根据需要选择相应的算法或行为

  10. 模板方法模式

    先定义父类,子类继承通用的方法,特殊的方法在子类重写。

  11. 访问者模式

    访问者模式是一种较为复杂的行为型设计模式,包含 访问者 和 被访问元素 两个主要组成部分,这些被访问的元素通常具有不同的类型,且不同的访问者可以对它们进行不同的访问操作。访问者模式使得用户可以在不修改现有系统的情况下扩展系统的功能,为这些不同类型的元素增加新的操作。

违背 “开闭模式” :简单工厂模式、外观模式、状态模式、访问者模式

不推荐:适配器模式

附录

  1. [外观模式、代理模式、中介者模式区](http://super-wei.top/2019/12/25/设计模式/行为型/5.1 外观模式、代理模式、中介者模式区别/)

  2. 使用策略模式&代理模式进行表单验证