观察者模式与发布-订阅模式的区别

245 阅读1分钟

观察者模式

在 DOM 上绑定事件处理函数addEventListener就是观察者模式最典型的用法,但观察者和被观察者之间还存在耦合,被观察者还是知道观察者的。

image.png

class Theme {
  constructor(public name: string) {}
  private state: number = 0
  private observerList: Observer[] = []
  getState(): number {
    return this.state
  }
  setState(state: number): void {
    this.state = state
    this.observerList.forEach((observer) => {
      observer.update(this)
    })
  }
  addObserver(observer: Observer): void {
    this.observerList.push(observer)
  }
}

class Observer {
  constructor(public name: string) {}
  update(theme: Theme): void {
    console.log(`${this.name}  ${theme.name} update ${theme.getState()}`)
  }
}

const theme = new Theme('dark')
const observer1 = new Observer('observer1')
const observer2 = new Observer('observer2')
theme.addObserver(observer1)
theme.addObserver(observer2)
theme.setState(1)
theme.setState(2)

发布-订阅模式

发布 - 订阅模式 中的发布者和订阅者不需要知道对方的存在,他们通过消息中心来进行通信,解耦更加彻底,Vue 有一套这样的事件机制,比如 EventBus。在多层组件的事件处理中,如果你觉得一层层 $on$emit 比较麻烦,而你又不想用 Vuex,那么可以使用 EventBus 来解决组件间的数据通信。

image.png

interface saveEventObiect {
  [key: string]: Function[]
}

class EventEmitter {
  private events: saveEventObiect = {}
  on(name: string, fn: Function) {
    this.events[name] = this.events[name] || []
    if (fn) this.events[name].push(fn)
  }

  emit(name: string, ...args: any[]) {
    if (this.events[name]) {
      this.events[name].forEach((fn) => fn.apply(this, args))
    }
  }
  off(name: string) {
    this.events[name] = []
  }
}

const emitter = new EventEmitter()



emitter.on('save', (a: any, b: any, c: any) => {
  console.log('save')
  console.log(a, b, c)
})


emitter.on('save', () => {
  console.log('save2')
})


emitter.emit('save', 'aa', 'bb', 'cc')