优化实战 第 39 期 - 观察者模式最佳实战

3,122 阅读2分钟

观察者模式

  • 模式定义

    observer.png

    定义了对象之间的一对多依赖关系,让多个观察者对象同时监听一个主体对象,当主体对象发生变化时,它的所有依赖者(观察者)都会收到通知并做相应的更新

    observer.jpeg

    通过原生 JS 的 自定义事件 可以实现该设计模式

  • 模式构成

    观察者(Observer)被观察者(Subject) 两个角色构成,两者是一个松耦合的关系,只需要维护一套观察者的集合即可

  • 模式作用

    将观察者和被观察者完全隔离解耦,让耦合的双方都依赖于抽象,而不是依赖具体

    使各观察者模块之间互不影响,易于扩展

  • 生活示例

    observer-comic.png

    在现实生活中,校园里的铃就是一个主体对象,而校园里的所有师生都是观察者,当铃声在特定的时间响起的时候,学校里的师生都能被通知并去做相应的事情

自定义事件

  • Event()构造函数

    document.dispatchEvent(new Event(eventName, {
      bubbles: '是否冒泡',  // 默认值为 false
    }))
    
  • CustomEvent()构造函数

    document.dispatchEvent(new CustomEvent(eventName, {
      detail: '需要被传递的业务数据',  // 默认值为 null
      bubbles: '是否冒泡',
    }))
    document.addEventListener(eventName, ({ detail }) => {
      console.log('业务数据:', detail)
    })
    

应用场景

  • 单个目标对象发生改变,需要通知多个观察者

    被观察者 Subject

    import observerA from './observerA'
    import observerB from './observerB'
    el.addEventListener('click', async () => {
      console.log('目标对象发生变化')
      document.dispatchEvent(new Event('taskStart'))
    })
    

    观察者 observerA

    document.addEventListener('taskStart', () => {
      console.log('观察者A执行操作')
    })
    

    观察者 observerB

    document.addEventListener('taskStart', () => {
      console.log('观察者B执行操作')
    })
    
  • 分模块协作需要解耦的

    被观察者 Subject

    import observerA from './observerA'
    el.addEventListener('click', async () => {
      console.log('目标对象发生变化')
      document.dispatchEvent(new Event('taskStart'))
    })
    

    观察者 observerA 以及创建新的被观察者

    import observerB from './observerB'
    document.addEventListener('taskStart', () => {
      console.log('观察者A执行操作')
      setTimeout(() => {
        console.log('观察者A执行操作完成')
        document.dispatchEvent(new Event('observerB'))
      }, 2000)
    })
    

    观察者 observerB

    document.addEventListener('observerB', () => {
      console.log('观察者B执行操作')
      setTimeout(() => {
        console.log('观察者B执行操作完成')
      }, 2000)
    })
    

    一起学习,加群交流看 沸点