首页 弘成IT资讯

Vue源码解析-发布订阅模式

2019-12-17 弘成IT
分享到:

  一、前言

  有一回面试,面试官问:

  了解发布订阅模式?

  我脑海中立刻闪现了《Head First设计模式》里讲的:
 

  Publishers + Subscribers = Observer Pattern

\

 
  我故作镇定,嘴角露出一丝微笑,仿佛下一秒钟面试官就会给我发offer。

  面试官也笑了,“不,它们不一样”。

  然后我就:

\
 

  So, 为什么我错了?观察者模式(Observer pattern),和发布订阅模式(Publish–subscribe pattern)到底是什么呢?

  二、发布订阅模式

  有些网站在注册用户成功后发一封激活邮件,用户收到邮件后点击激活链接后才能使用该网站。一般的做法是在注册用户业务逻辑中调用发送邮件的逻辑。这样用户业务就依赖于邮件业务。如果以后改为短信激活,注册用户业务逻辑就必须修改为调用发送短信的逻辑。如果要注册后给用户加点积分,再加一段逻辑。经过多次修改,我们发现很简单的注册用户业务已经越来越复杂,越来越难以维护。相信很多开发者都会有类似痛苦的经历。

\
 

  即使用户业务实现中对其他业务是接口依赖,也避免不了业务变化带来的依赖影响。怎么办?解耦!将注册用户业务逻辑中注册成功后的处理剥离出来。

  再回头看看“订阅杂志”,如果没有邮局,出版社就必须自己将杂志送达所有消费者。这种情形就和现在的注册用户业务一样。我们发现问题了,在用户业务和其他业务之间缺少了邮局所扮角色。

  我们把邮局抽象成一个管理消息的地方,叫“消息管理器”。注册用户成功后发送一个消息给消息管理器,由消息管理器转发该消息给需要处理的业务。现在,用户业务只依赖于消息管理器了,它再也不会为了注册用户成功后的其他处理而烦恼。

\

  注册用户的改造就是借鉴了“订阅杂志”这样原始的模式。我们再进一步抽象,用户业务就是消息的“生产者”,它将消息发布到消息管理器。邮件业务就是消息的“消费者”,它将收到的消息进行处理。邮局可以订阅很多种杂志,杂志都是通过某种编号来区分;消息管理器也可以管理多种消息,每种消息都会有一个“主题”来区分,消费者都是通过主题来订阅的。

 \

  发布-订阅消息模式已经呈现在我们面前,利用它可以产生更灵活、更松散耦合的系统。

  Vue中的发布订阅模式 ( 形式不局限于函数, 形式可以是对象等 ) :

  1. 中间的全局的容器, 用来存储可以被触发的东西( 函数, 对象 )
 
  2. 需要一个方法, 可以往容器中传入东西 ( 函数, 对象 )

  3. 需要一个方法, 可以将容器中的东西取出来使用( 函数调用, 对象的方法调用 )

  页面中的变更 ( diff ) 是一组件为单位

  1. 如果页面中只有一个组件 ( Vue 实例 ), 不会有性能损失

  2. 但是如果页面中有多个组件 ( 多 watcher 的一种情况 ), 第一次会有 多个组件的 watcher 存入到 全局watcher 中.

  a. 如果修改了局部的数据( 例如其中一个组件的数据 )

  b. 表示只会对该组件进行 diff 算法, 也就是说只会重新生成该组件的 抽象语法树

  c. 只会访问该组件的 watcher

  d. 也就表示再次往全局存储的只有该组件的 watcher

  e. 页面更新的时候也就只需要更新一部分

  三、总结

  从表面上看:

  • 观察者模式里,只有两个角色 —— 观察者 + 被观察者

  • 而发布订阅模式里,却不仅仅只有发布者和订阅者两个角色,还有一个经常被我们忽略的 —— 经纪人Broker

  往更深层次讲:

  • 观察者和被观察者,是松耦合的关系

  • 发布者和订阅者,则完全不存在耦合

  从使用层面上讲:

  • 观察者模式,多用于单个应用内部

  • 发布订阅模式,则更多的是一种跨应用的模式(cross-application pattern),比如我们常用的消息中间件

弘成IT版权与免责声明
1、凡本网站注明稿件来源为:弘成IT的所有文字、图片和音视频稿件,版权均属本网站所有,任何媒体、网站或个人未经本网协议授权不得转载、链接、转贴或以其他方式复制发表。已经本网协议授权的媒体、网站,在下载使用时必须注明“稿件来源:弘成IT”,违者本网将依法追究责任。
2、本网注明稿件来源为其他媒体的文/图等稿件均为转载稿,本网转载出于非商业性的教育和科研之目的,并不意味着赞同其观点或证实其内容的真实性。如转载稿涉及版权等问题,请作者在两周内速来电或来函联系。