持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情
前情提要
现在可能有一部分jym分不太清观察者和订阅者的区别。甚至认为他们俩就是相同的东西。不要急于反驳,问问你身边的小哥哥或者小姐姐或者老哥哥老姐姐你就知道了。
直接上硬菜:观察者和发布订阅模式最根本的区别是什么?
观察者和发布订阅模式最根本的区别就是观察者是低耦合模式,而发布订阅是完全解耦的模式。发布订阅模式比观察者模式多了一个中间经纪人或者说叫事件中心。也就因为这个中间经纪人使得发布和订阅完全解耦。而观察者模式没有这个中间经纪人,它能实现的是降低耦合。上一篇文章已经讲过发布订阅模式了,那么今天讲一讲观察者模式,jym可以有个更为清晰的理解。
基于vue的响应式看什么是观察者模式?
观察者模式的结构
- 观察者 -- Watcher : 又叫订阅者
- 每一个观察者都会有一个:update方法,当事件发生的时候,观察者具体要做的事情
- 目标 -- Dep : 又叫发布者
- 该属性具有一个数组:subs。用来存储所有的观察者
- 具有一个方法:addSub()。用来添加观察者
- 具有一个方法:notify()。当事件发生的时候也就是发布的时候,调用所有观察者的update方法。
- 事件中心:不存在的,观察者不存在事件中心。
动手实现一个观察者模式(这里暂时不考虑传参的情况,这里主要是借助vue理解观察模式)
-
代码
// 对于发布者其实起名target更为贴切,但是因为是基于vue,vue中观察者模式的发布者就叫dep,咱们这里进行保持统一吧 // 发布者 - 目标 class Dep { constructor() { this.subs = []; // 用来存放所有观察者的中心. } addSub(sub) { if (sub && sub.update) this.subs.push(sub); // 这里是为了保证update存在,否则当垃圾数据处理 } // 发布 notify() { this.subs.forEach(sub => { sub.update() }) } } // 观察者 - watcher class Watcher { // 更新方法 update() { console.log('此时我开始进行DOM更新操作。') } } const depOfIphone = new Dep(); const watcherOfIphone = new Watcher(); depOfIphone.addSub(watcherOfIphone); depOfIphone.notify(); -
在浏览器中运行的结果如下图:
总结
通过前后两篇的文章作为对比我们可以发现两者的区别如下:
- 调度方式
- 观察者模式的调度方式是目标调度,当事件触发,dep就会去调用观察者模式的update,所以观察者模式的订阅者与发布者之间存在依赖关系。
- 发布订阅模式的调度方式是事件中心调度,发布者和订阅者两者之间并不知道彼此的存在。
- 流程图:
-
观察者:
graph TD 目标_发布者 -- 触发事件 --> 观察者_订阅者 观察者_订阅者 -- 订阅事件 --> 目标_发布者 -
发布订阅:
graph TD 发布者 -- 发布 --> 事件中心 -- 触发 --> 订阅者 订阅者 -- 订阅 --> 事件中心
-