设计模式,其实就是为软件设计中普遍存在的各种问题所提出的各种方案。

# 单例模式

概念:全局作用域下只会创建一次实例对象,让所有需要调用的地方都共享这一单例对象。

应用场景:

  • 全局模态框
  • vuex、vue-router、redux
class Singleton {
  private static instance = null

  public static getInstance() {
    if (Singleton.instance === null) {
      Singleton.instance = new Singleton()
    }
    return Singleton.instance
  }

  // ...
}

export const singleton = Singleton.getInstance()

# 工厂模式

概念:创建对象的常用设计模式,不暴露创建对象的具体逻辑,而是将逻辑封装在一个函数(工厂)中。

应用场景:

  • 创建对象
function newFactory(constructor, ...args) {
  const obj = new Object()
  obj.__proto__ = constructor
  const res = constructor.apply(obj, args)
  return typeof res === 'object' ? res : obj
}
  • 原型式继承
function extendFactory(parent) {
  const obj = new Object()
  obj.__proto__ = parent
  return obj
}

# 策略模式

定义一系列算法,并且将它们一个个封装起来,将算法的使用和算法的实现分离开来

  • 策略类:可变。封装不同策略的算法。
  • 环境类:不可变。接收不同的客户请求,将其委托给对应的策略。

应用场景:

  • 表单验证

    • 策略类:不同的验证逻辑
    • 环境类:接收用户验证要求,委托给不同的策略
  • 对接不同应用接口,如:对接微信、抖音等不同应用的登录接口

    • 策略类:不同应用的登录接口
    • 环境类:接收不同应用的用户登录请求,委托给不同的策略

# 观察者模式

概念:

  • 定义了对象之间的一种一对多的依赖关系。当一个对象的状态发生改变时,依赖于它的所有对象都会得到通知,使其自动更新。

  • 行为型模式:关注的是对象之间的通讯(观察者和被观察者之间的通信)

  • 观察者与被观察者直接交互

  • 被观察者知道有哪些观察者

应用场景:

  • Vue2 响应式实现:观察者模式 + Object.defineProperties
    • 被观察者:data 数据
    • 观察者:各种 Watcher,如:Render Watcher、Computed Watcher 等。

# 发布订阅模式

概念:

  • 发布订阅是一种消息范式
  • 发布者不会将消息直接发送给订阅者,而是将消息分为不同的类别,无需了解哪些订阅者可能存在(消息代理进行通信)

应用场景:

  • EventBus

# 观察者模式 vs 发布订阅模式

  • 观察者模式

    • 行为式模式
    • 被观察者知道有哪些观察者
    • 被观察者与观察者直接通信
  • 发布订阅模式

    • 消息范式
    • 发布者不知道有哪些订阅者
    • 发布者和订阅者不会直接通信,
    • 而是将消息分为不同的类别,通过事件代理的方式,通知订阅者

# 代理模式

概念:为一个对象提供一个代用品或者占位符,控制该对象的访问。

应用:

  • Proxy 对象
  • 缓存代理:将计算开销比较大的数据进行缓存,二次计算的时候命中缓存直接从缓存里面获取计算结果。
  • 虚拟代理:图片懒加载。

# 装饰者模式

概念:

  • 在不改变对象自身的基础上,在程序运行期间给对象动态添加额外的方法。
  • 将类的核心职责和装饰功能区分开来。

应用场景:

  • 动态地扩展对象功能
  • 避免过度子类化:有多个功能相似但略有不同的对象。