观察者模式是什么?

观察者模式是对象中的一种一对多的依赖关系,当对应的状态发生改变时,执行相应的更新。

观察者模式有两个概念,分别是:

  • 目标(发布者),发布者它会记录所有的订阅者,当状态发生改变时,由发布者通知订阅者
  • 观察者(订阅者) 所有的订阅者都有一个update方法,这个方法是用于处理状态发生改变时的业务。

Vue响应机制中使用了观察者模式,在vue响应机制中,当数据变化的时候会调用观察者的update方法,update方法内部就是更新视图

在观察者模式中,订阅者的update方法是由发布者调用的。

实现一个简单的观察者模式

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>观察者模式</title>
  7. </head>
  8. <body>
  9. <script>
  10. // 目标-发布者
  11. class Dep {
  12. constructor() {
  13. this.subs = [];
  14. }
  15. // 添加观察者
  16. addSub(sub) {
  17. if (sub && sub.update) {
  18. this.subs.push(sub)
  19. }
  20. }
  21. // 通知观察者
  22. notify() {
  23. this.subs.forEach(sub => {
  24. sub.update()
  25. })
  26. }
  27. }
  28. // 观察者-订阅
  29. class Watcher {
  30. update() {
  31. console.log("update")
  32. }
  33. }
  34. let dep = new Dep()
  35. let watcher = new Watcher()
  36. dep.addSub(watcher)
  37. dep.notify()
  38. </script>
  39. </body>
  40. </html>

发布订阅模式是什么?

发布订阅模式是对象中的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖与它的对象都将得到状态改变的通知。

发布定于模式有三个概念,分别是:

  • 订阅者,订阅者的作用是:向调度中心注册一个事件,这个事件的作用是处理状态改变后的业务。
  • 发布者,发布者的作用是:向调度中心发起一个状态改变的通知。
  • 调度中心,调度中心的作用是:将发布者状态改变时向调度中心发送的通知,告知给订阅者。

看似很陌生,其实在工作中经常会用到。例如:

  • node.js 中 EventEmitter 中的 onemit
  • vue.js 中的 $on$emit

他们都使用了发布订阅模式

例子

我们就拿微信公众号来举例子,我们很喜欢一个公众号的文章,但是我们不知道这个公众号什么时候发布文章,要不定时的去翻一翻。这个时候我们可以订阅这个公众号,每当这个公众号发布了新的文章的时候,我们就会收到通知。

这个例子中的发布者就是当前这个**公众号**,我们就是**订阅者**,微信就是**调度中心**

实现一个简单的发布订阅模式

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>发布订阅模式</title>
  7. </head>
  8. <body>
  9. </body>
  10. </html>
  11. <script>
  12. class EventEmitter {
  13. constructor() {
  14. //设置对象的原型
  15. // { 'click': [fn1, fn2], 'change': [fn] }
  16. this.subs = Object.create(null)
  17. }
  18. // 注册事件
  19. $on(eventType, handler) {
  20. this.subs[eventType] = this.subs[eventType] || []
  21. this.subs[eventType].push(handler)
  22. }
  23. // 触发事件
  24. $emit(eventType) {
  25. if (this.subs[eventType]) {
  26. this.subs[eventType].forEach(handler => {
  27. handler();
  28. })
  29. }
  30. }
  31. }
  32. </script>
  33. <script>
  34. // 调度中心
  35. let dispatch = new EventEmitter()
  36. // 注册事件(订阅消息) ,当调度中心有新的信息过来的时候,会触发相对应的函数
  37. dispatch.$on('dataChange', () => {
  38. console.log('dataChange')
  39. })
  40. dispatch.$on('dataChange', () => {
  41. console.log('dataChange1')
  42. })
  43. // 触发事件(发布消息),向调度中心发布信息
  44. dispatch.$emit('dataChange')
  45. </script>

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

相同点:

都是对象中的一种一对多的依赖关系,当对应的状态发生改变时,执行相应的更新。

不同点:

1、发布者模式有调度中心,观察者模式没有调度中心。
2、发布者模式的更新是由调度中心发起的,而观察者模式的更新是由目标(订阅者)发起的
3、发布者模式,双方并不知道对方的存在,而观察者模式是必须要知道的,基础自定义事件。
4、发布者模式是低耦合的,而观察者是高耦合的。

使用场景:
观察者模式:vue依赖追踪、原生事件
发布订阅模式:vue的组件之间的通信EeventBus,react合成事件

下面的文章讲的很清楚,可以具体看看:

https://www.jianshu.com/p/594f018b68e7

https://www.cnblogs.com/liuhp/p/12221144.html