设计者模式 -- 简单实现

单例模式

  • 特点:只存在一个实例,可以用于状态机,store状态管理等

核心代码

function Singleton() {}
let instance = null
const singleton = function () {
  if (!instance) instance = new Singleton()
}
const single = singleton()

缺点

  1. 最后调用的时候 实例 和 构造函数 Person 没有关系了
  2. 没有用到 new 了

优化代码

const Singleton = (function () {
  class Singleton {}
  let instance = null
  return function () {
    if (!instance) instance = new Single()
    return instance
  }
})()

const singleton = new Singleton()

观察者模式

  • 特点:有两个构造函数,一个是观察者,一个是被观察者

实现逻辑

  • 有两个构造函数,一个为观察者构造函数,一个为被观察对象构造函数
  1. 观察者构造函数
  • 观察者构造函数有两个参数
    • 观察者的name
    • 观察者观察到被观察者状态变化之后的处理(回调函数)
  1. 被观察者构造函数
  • 被观察者有以下关键参数
    • 自己的状态
    • 观察者列表
    • 设置状态的方法
    • 添加观察者的方法
    • 删除观察者的方法

代码实现

class Observer {
  constructor(name, cb) {
    this.name = name
    if (typeof cb !== 'function') {
      throw new Error('cb 必须是一个函数')
    }
    this.cb = cb
  }
}

class ObserveSubject {
  observers = []
  constructor(state) {
    this.state = state
  }
  // 设置状态
  setState(state) {
    this.state = state
    // console.log(`状态变化了, 现在在${state}`)
    this.observers.forEach((item) => {
      item.cb(state)
    })
  }
  addObserver(obs) {
    // 观察者不能重复
    if (this.observers.includes(obs)) {
      // console.log(`当前观察者已经在观察者列表了`)
      return
    }
    this.observers.push(obs)
  }
  delObserver(obs) {
    // 如果当前观察者在观察者列表,则删除,否则不进行操作
    this.observers = this.observers.filter((item) => item !== obs)
  }
}

const obs1 = new Observer('obs1', (state) => {
  console.log(`obs1观察到被观察者的变化了,状态变为了${state}`)
})

const obs2 = new Observer('obs2', (state) => {
  console.log(`obs2观察到被观察者的变化了,状态变为了${state}`)
})

发布订阅模式

  • 由一个类就可以同时实现发布和订阅功能

实现逻辑

  • 有一个订阅的函数
  • 有一个取消订阅的函数
  • 有一个发布事件的函数

代码

class EventEmit {
  // 定义一个存储发布事件和回调函数列表的对象,一个事件类型可以支持多个回调函数
  eventObj = {}
  on(type, fn) {
    if (!this.eventObj[type]) {
      this.eventObj[type] = [fn]
      return
    }
    this.eventObj[type].push(fn)
  }
  off(type, fn) {
    // 存在两种情况:如果函数存在,则只取消订阅该函数,如果不存在,则将该类型所有函数都取消
    if (!fn) {
      delete this.eventObj[type]
      return
    }
    this.eventObj[type] = this.eventObj[type].filter((item) => item !== fn)
  }
  emit(type, param) {
    if (this.eventObj[type]) {
      this.eventObj[type].forEach((item) => {
        item(param)
      })
    }
  }
}

posted on 2025-03-12 21:46  shenhf  阅读(34)  评论(0)    收藏  举报

导航