观察者模式:构建松耦合、可扩展的系统架构

367 阅读2分钟

观察者模式是一种行为设计模式,它定义了一种一对多的依赖关系,当主体对象的状态发生变化时,所有依赖它的观察者对象都会得到通知并自动更新。

observer.png

问题分析

假如有两种类型的对象:顾客商店。顾客对某个特定品牌的产品非常感兴趣,而该产品很快将会在商店里出售。

顾客可以每天来商店看看产品是否到货。但如果商品尚未到货时,绝大多数来到商店的顾客都会空手而归。

observer.png

另一方面,每次产品到货时,商店可以向所有顾客发送邮件(可能会被视为垃圾邮件)。这样,部分顾客无需反复前往商店,但也可能会对产品没兴趣的其他顾客造成不必要的打扰。

要么让顾客浪费时间检查产品是否到货, 要么让商店浪费资源去通知没有需求的顾客。

解决方案

值得关注的状态的对象通常被称为目标,由于它要将自身的状态改变通知给其他对象,所以也将其称为发布者(publisher)。所有希望关注发布者状态变化的其他对象被称为订阅者(subscribers)。

观察者模式为发布者类添加订阅机制,让每个对象都能订阅或取消订阅发布者事件流。

solution_01.png

订阅机制允许对象订阅事件通知

无论何时发生了重要的发布者事件, 它都要遍历订阅者并调用其对象的特定通知方法。

solution_02.png

发布者调用订阅者对象中的特定通知方法来通知订阅者

观察者模式能够帮助我们构建松耦合、可扩展的系统架构,并实现对象之间的动态通信和协作。该模式将被观察者与观察者之间的依赖关系解耦,使得系统更易于维护和扩展。

模式实现

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

    被观察者 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)
    })