# 观察者模式

# 参考

https://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/observer.html (opens new window)

# 定义

建立一种对象间的一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。

发布订阅模式是最常用的一种观察者模式的实现,发布订阅模式让两个对象低耦合的联系在一起,双方不必清楚彼此的实现,依然能够进行互相通信。

# 应用场景

在JavaScript开发中常见的事件模型,就属于发布订阅模式。另外常见的dom绑定事件,ajax异步请求回调都属于发布订阅模式的一种体现。

# 优点

  • 实现了对象的解耦,以及在异步编程中时间的解耦。

# 缺点

  • 为了实现对象间的解耦,弱化了对象之间的联系。过度的使用,使得对象必要的联系被深埋在后,会导致程序难以跟踪、维护。

# 代码实例


// JavaScript发布-订阅模式的简单实现
class EventEmitter {
  private events: object = {}
  on(eventName: string, fn: Function): void {
    Array.isArray(this.events[eventName]) ? this.events[eventName].push(fn) : (this.events[eventName] = [fn])
  }
  emit(eventName: string): boolean {
    if (this.haveEvents(eventName)) {
      this.events[eventName].forEach(fn => {
        fn()
      })
      return true
    }
    return false
  }
  off(eventName: string, fn?: Function): boolean {
    if (this.haveEvents(eventName)) {
      const fnIndex = this.events[eventName].findIndex(f => f === fn)
      if (typeof fn === 'function' && fnIndex >= 0) {
        this.events[eventName].splice(fnIndex, 1)
      } else {
        this.events[eventName] = []
      }
      return true
    }
    return false
  }
  haveEvents(eventName: string): boolean {
    return this.events[eventName] && this.events[eventName].length
  }
}

const EE = new EventEmitter()
const log1 = () => console.log('1')
const log1_1 = () => console.log('1_1')
const log1_1_1 = () => console.log('1_1_1')
const log2 = () => console.log('2')

EE.on('event1', log1)
EE.on('event1', log1_1)
EE.on('event1', log1_1_1)
EE.on('event2', log2)
EE.off('event1', log1_1)
EE.emit('event1')
EE.emit('event2')
console.log(EE)
上次更新: 5/17/2020, 9:24:33 AM