资讯专栏INFORMATION COLUMN

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

ysl_unh / 665人阅读

摘要:或许以前认为订阅发布模式是观察者模式的一种别称,但是发展至今,概念已经有了不少区别。参考文章订阅发布模式和观察者模式真的不一样

首选我们需要先了解两者的定义和实现的方式,才能更好的区分两者的不同点。

或许以前认为订阅发布模式是观察者模式的一种别称,但是发展至今,概念已经有了不少区别。

订阅发布模式
在软件架构中,发布-订阅是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。而是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话)可能存在。同样的,订阅者可以表达对一个或多个类别的兴趣,只接收感兴趣的消息,无需了解哪些发布者(如果有的话)存在。

或许你用过 eventemitter、node 的 events、Backbone 的 events 等等,这些都是前端早期,比较流行的数据流通信方式,即订阅发布模式

从字面意思来看,我们需要首先订阅,发布者发布消息后才会收到发布的消息。不过我们还需要一个中间者来协调,从事件角度来说,这个中间者就是事件中心,协调发布者和订阅者直接的消息通信。

完成订阅发布整个流程需要三个角色:

发布者

事件中心

订阅者

以事件为例,简单流程如下:

发布者->事件中心<=>订阅者,订阅者需要向事件中心订阅指定的事件 -> 发布者向事件中心发布指定事件内容 -> 事件中心通知订阅者 -> 订阅者收到消息(可能是多个订阅者),到此完成了一次订阅发布的流程。

简单的代码实现如下:

class Event {
  constructor() {
    // 所有 eventType 监听器回调函数(数组)
    this.listeners = {}
  }
  /**
   * 订阅事件
   * @param {String} eventType 事件类型
   * @param {Function} listener 订阅后发布动作触发的回调函数,参数为发布的数据
   */
  on(eventType, listener) {
    if (!this.listeners[eventType]) {
      this.listeners[eventType] = []
    }
    this.listeners[eventType].push(listener)
  }
  /**
   * 发布事件
   * @param {String} eventType 事件类型
   * @param {Any} data 发布的内容
   */
  emit(eventType, data) {
    const callbacks = this.listeners[eventType]
    if (callbacks) {
      callbacks.forEach((c) => {
        c(data)
      })
    }
  }
}

const event = new Event()
event.on("open", (data) => {
  console.log(data)
})
event.emit("open", { open: true })

Event 可以理解为事件中心,提供了订阅和发布功能。

订阅者在订阅事件的时候,只关注事件本身,而不关心谁会发布这个事件;发布者在发布事件的时候,只关注事件本身,而不关心谁订阅了这个事件。

观察者模式
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个目标对象,当这个目标对象的状态发生变化时,会通知所有观察者对象,使它们能够自动更新。

观察者模式我们可能比较熟悉的场景就是响应式数据,如 Vue 的响应式、Mbox 的响应式。

观察者模式有完成整个流程需要两个角色:

目标

观察者

简单流程如下:

目标<=>观察者,观察者观察目标(监听目标)-> 目标发生变化-> 目标主动通知观察者。

简单的代码实现如下:

/**
 * 观察监听一个对象的变化
 * @param {Object} subject 观察的目标
 * @param {Function} callback 目标变化触发的回调
 */
function observer(subject, callback) {
  Object.defineProperty(subject, "description", {
    get() {
      return this.data.description
    },
    set(val) {
      this.data.description = val
      // 目标主动通知观察者
      callback && callback(val)
    },
  })
}

可运行例子如下:



  
    
    
    
  
  
    
原来的值

原来的值

两者的区别在哪?

角色角度来看,订阅发布模式需要三种角色,发布者、事件中心和订阅者。二观察者模式需要两种角色,目标和观察者,无事件中心负责通信。

从耦合度上来看,订阅发布模式是一个事件中心调度模式,订阅者和发布者是没有直接关联的,通过事件中心进行关联,两者是解耦的。而观察者模式中目标和观察者是直接关联的,耦合在一起(有些观念说观察者是解耦,解耦的是业务代码,不是目标和观察者本身)。

两者的优缺点?

优缺点都是从前端角度来看的。

订阅发布模式优点

灵活

由于订阅发布模式的发布者和订阅者是解耦的,只要引入订阅发布模式的事件中心,无论在何处都可以发布订阅。同时订阅发布者相互之间不影响。

订阅发布模式在使用不当的情况下,容易造成数据流混乱,所以才有了 React 提出的单项数据流思想,就是为了解决数据流混乱的问题。

订阅发布模式缺点

容易导致代码不好维护

灵活是有点,同时也是缺点,使用不当就会造成数据流混乱,导致代码不好维护。

性能消耗更大

订阅发布模式需要维护事件列队,订阅的事件越多,内存消耗越大。

观察者模式优点

响应式

目标变化就会通知观察者,这是观察者最大的有点,也是因为这个优点,观察者模式在前端才会这么出名。

观察者模式缺点

不灵活

相比订阅发布模式,由于目标和观察者是耦合在一起的,所以观察者模式需要同时引入目标和观察者才能达到响应式的效果。而订阅发布模式只需要引入事件中心,订阅者和发布者可以不再一处(同一个页面)。

参考文章

订阅发布模式和观察者模式真的不一样

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/106987.html

相关文章

  • 发布订阅模式实现及发布订阅模式察者模式不同

    摘要:发布订阅者模式中,订阅者是不知道也不关心事件是为什么触发,是由哪一个事件触发,只知道事件触发时候,会告诉自己。然而,在发布订阅模式中,发布者和订阅者不知道对方的存在。在发布订阅模式中,组件是松散耦合的,正好和观察者模式相反。 概念 发布订阅者模式,是javascript甚至大多数语言都有的语言模式,比较概念的解释是, 订阅者把自己想订阅的事件注册到调度中心,当该事件触发时候,发布者发布...

    YanceyOfficial 评论0 收藏0
  • 发布订阅模式实现及发布订阅模式察者模式不同

    摘要:发布订阅者模式中,订阅者是不知道也不关心事件是为什么触发,是由哪一个事件触发,只知道事件触发时候,会告诉自己。然而,在发布订阅模式中,发布者和订阅者不知道对方的存在。在发布订阅模式中,组件是松散耦合的,正好和观察者模式相反。 概念 发布订阅者模式,是javascript甚至大多数语言都有的语言模式,比较概念的解释是, 订阅者把自己想订阅的事件注册到调度中心,当该事件触发时候,发布者发布...

    Jensen 评论0 收藏0
  • 察者模式发布订阅模式(JS)

    摘要:最近被人问到设计模式,观察者模式和发布订阅模式二者有什么区别。观察者模式观察者模式,目标和观察者是基类,目标提供维护观察者的一系列方法,观察者提供更新接口。 最近被人问到设计模式,观察者(Observer)模式和发布(Publish)/订阅(Subscribe)模式二者有什么区别。其实这两种模式还是有些许差异的,本质上的区别是调度的方式不同。 观察者模式 观察者模式,目标和观察者是基类...

    Sanchi 评论0 收藏0
  • ObserverMediator模式区别

    摘要:举个例子淘宝商铺卖家在淘宝上开了一个相机店最近都有意愿去买但是觉得价格稍贵,因此暂时不打算入手,想等价格稍微便宜一点后再入手,所以这个人通过淘宝先关注卖家的相机店。等到卖家的相机打折后,淘宝会向这个人推送打折消息。 Observer观察者模式 Observer观察者模式和Pub/sub模式事实上都是同一套路。这种模式建立起了不同对象之间的依赖关系: showImg(https://se...

    wapeyang 评论0 收藏0
  • 察者模式

    摘要:细思不恐主旨在设计模式中,观察者模式的主旨则是定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 简单说两句 观察者模式,是对象行为型模式中的一种,有的时候人们也叫他发布/订阅模式。当我们需要在一个对象状态改变的时候通知到其它对象,这时候就可以考虑一下观察者模式。 细思不恐 showImg(https://segmentfault....

    魏宪会 评论0 收藏0

发表评论

0条评论

ysl_unh

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<