JS中观察者模式与发布订阅模式区别对比

目录
文章目录隐藏
  1. 观察者模式
  2. 发布-订阅模式
  3. 二者区别
  4. 结语

最近,再重学 JavaScript 知识,对于观察者模式与发布订阅模式有了更深层次的了解,这也就是我们所说的“温故而知新”,今天我们来看看它们之间有哪些区别。

观察者模式

当对象之间存在一对多的依赖关系时,当被观察的对象状态发生改变时,所有观察它的对象都会收到通知,这就是观察者模式。

基本思想

在观察者模式中,只有两种主体:目标对象 (Subject) 和 观察者 (Observer)。
在观察者模式中,Subject 对象拥有添加、删除和通知一系列 Observer 的方法等,而 Observer 对象拥有 update 更新方法等。在 Subject 对象添加了一系列 Observer 对象之后,Subject 对象则维持着这一系列 Observer 对象,当有关状态发生变更时 Subject 对象则会通知这一系列 Observer 对象进行更新。

优点

  • 耦合度高,通常用来实现一些响应式的效果;
  • 角色很明确,没有事件调度中心作为中间者,目标对象Subject和观察者Observer都要实现约定的成员方法;
  • 双方联系紧密,目标对象的主动性很强,自己收集和维护观察者,并在状态变化时主动通知观察者更新;

实现

// 目标对象
class Subject {
  constructor() {
    this.observers = []
  }

  add (observer) {
    this.observers.push(observer)
  }

  notify() {
    this.observers.map(observer => {
      if (observer && typeof observer.update === 'function') {
        observer.update()
      }
    })
  }

  remove(observer) {
    const idx = this.observers.findIndex(itm => itm === observer)
    if (idx !== -1) {
      this.observers.splice(idx, 1)
    }
  }
}

// 观察者
class Observer {
  constructor(name) {
    this.name = name
  }

  update() {
    console.log(`${this.name} updated`)
  }
}

const subject = new Subject()
const o1 = new Observer('Nina')
const o2 = new Observer('Jack')

subject.add(o1)
subject.add(o2)

console.log('第一次通知:')
subject.notify()

subject.remove(o1)

console.log('删除 Nina 后,再次通知:')
subject.notify()

打印结果为:

观察者模式

发布-订阅模式

基于一个事件(主题)通道,希望接收通知的对象 Subscriber 通过自定义事件订阅主题,被激活事件的对象 Publisher 通过发布主题事件的方式通知各个订阅该主题的 Subscriber 对象,这就是发布订阅模式。
发布订阅模式中有三个角色:发布者 Publisher ,事件调度中心 Event Channel ,订阅者 Subscriber 。

特点

  • 发布订阅模式中,对于发布者Publisher和订阅者Subscriber没有特殊的约束,他们借助事件调度中心提供的接口发布和订阅事件,互不了解对方是谁;
  • 松散耦合,灵活度高,常用作事件总线;
  • 易理解,可类比于DOM事件中的dispatchEventaddEventListener

缺点

  • 当事件类型越来越多时,难以维护,需要考虑事件命名的规范,也要防范数据流混乱。

实现

class EventEmitter {
  constructor() {
    this.list = {}
    if (!EventEmitter.instance) {
      EventEmitter.instance = this
    }
    return EventEmitter.instance
  }

  on(name, fn) {
    if (!this.list[name]) {
      this.list[name] = []
    }
    this.list[name].push(fn)
  }

  emit(...rest) {
    const name = ([].shift.call(rest))
    const fns = this.list[name] || []
    fns.forEach((fn) => {
      fn.apply(this, rest)
    })
  }

  off(name) {
    this.list[name] = []
  }

  clean() {
    this.list = {}
  }
}

const e1 = new EventEmitter()
e1.on('go', (name) => console.log(`${name} 走了`))
e1.on('come', (name) => console.log(`${name} 来了`))

e1.emit('go', 'Nina')
e1.emit('go', 'Jack')
e1.emit('come', 'Bill')

打印结果为:

发布-订阅模式

二者区别

  • 概念与实现上
    • 从概念上理解,两者没什么不同,都在解决对象之间解耦,通过事件的方式在某个时间点进行触发,监听这个事件的订阅者可以进行相应的操作。
    • 在实现上有所不同,观察者模式对订阅事件的订阅者通过发布者自身来维护,后续的一些列操作都要通过发布者完成。发布订阅模式是订阅者和发布者中间会有一个事件总线,操作都要经过事件总线完成。
  • 耦合
    • 观察者模式是面向目标和观察者编程的,用于耦合目标和观察者。观察者和被观察者之间还存在耦合,被观察者还是知道观察者的;
    • 发布 – 订阅模式是面向调度中心编程的,用于解耦发布者和订阅者。发布者和订阅者不需要知道对方的存在,通过消息代理进行通信,解耦更加彻底;
  • 关系
    • 观察者模式的观察者和被观察者就像 商家-顾客 的关系,当商品有更新等,商家会直接通知订阅的顾客。
    • 发布订阅模式的发布者和订阅者,就像 商家-APP-顾客 的关系,顾客(订阅者)在 APP 上订阅商品通知,待商品有更新时,商家(发布者)通过 APP 通知订阅的顾客(订阅者)。
  • 从使用层面上讲
    • 观察者模式,多用于单个应用内部;
    • 发布订阅模式,更多的是一种跨应用的模式(cross-application pattern),比如消息中间件;

结语

以上就是 javascript 中关于观察者模式与发布订阅模式区别,一点小小的学习总结,希望对大家有用。

「点点赞赏,手留余香」

1

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
码云笔记 » JS中观察者模式与发布订阅模式区别对比

发表回复