阅读 42

发布订阅模式 vs 观察者模式

前言

一直以来,都以为发布订阅模式和观察者模式是一个东西,直到无意看到一篇文章才知道,他们是有区别的~~~那他们的区别到底是什么呢?

发布订阅模式属于广义上的观察者模式

发布订阅模式是最常用的一种观察者模式的实现,并且从解耦和重用角度来看,更优于典型的观察者模式。

从代码看区别

发布订阅模式

let fs = require('fs');
let path = require('path');

let namePath = path.resolve(__dirname, 'name.txt');
let eagPath = path.resolve(__dirname, 'age.txt')

/**
 * 发布 -> [中间代理] <- 订阅
 *  发布和订阅两者之间没有任何关系,通过的都是中间代理。比如你想订一份麻辣烫,你不会去跟店家说,你会找外卖平台,跟外卖平台说我要订一碗麻辣烫。然后店家麻辣烫做好了,会通知外卖平台做好了,你可以送餐了。
 */

 function Events() {
    this.callbacks = [];
    this.results = [];
 }

 // 订阅
 Events.prototype.on = function(callback) {
   this.callbacks.push(callback);
 }

 // 发布
 Events.prototype.emit = function(data) {
   this.results.push(data);
   this.callbacks.forEach(v => v(this.results));
 }

 let e = new Events()

 e.on(function(arr) {
   if(arr.length === 2) {
    console.log(arr)
   }
 })


/**
 * 注意事项:
 *  异步不能使用try catch
 */
fs.readFile(namePath, 'utf8', function(err, data) {
  e.emit(data)
})

fs.readFile(eagPath, 'utf8', function(err, data) {
  e.emit(data)
})
复制代码

观察者模式

 /**
  * 观察者模式(vue是典型的观察者模式) 
  *  观察者有观察者和被观察者,如果被观察者数据变化了 会通知观察者 (是有关系的)
  */

  // 被观察者 [被观察者中 要包括观察者]
  // 比如我要观察我家小宝宝的心情 (心情好 || 心情不好)
  class Subject {
    constructor(name) {
      this.name = name;
      this.observers = [];  // 观察者 要存放在被观察者中
      this.state = '心情很美丽'
    }
    // 被观察者要提供一个接受观察者的方法
    attach(observer) {
      this.observers.push(observer);  // 存放所有的观察者
    }
    setState(newState) {  // 更改被观察者的状态
      this.state = newState;
      this.observers.forEach(v => v.update(newState))
    }
  }

  // 观察者 (需要把观察者注册到被观察者中)
  class Observer {
    constructor(name) {
      this.name = name;
    }
      update(newState) {  // 用来通知所有的观察者状态更新了
        console.log(`${this.name}说: 宝宝${newState}`)
      }
  }

  let sub = new Subject('小宝宝');
  let o1 = new Observer('爸爸');
  let o2 = new Observer('妈妈');

  sub.attach(o1);
  sub.attach(o2);
  sub.setState('心情不好了, 呜呜~~~');
复制代码