javaScript 观察者模式和发布订阅模式

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

基本概念

发布订阅模式

在这个模式中,发布者(或者说是主题)并不直接发送消息给订阅者,而是通过调度中心(或者叫消息代理)来传递消息。 发布者(或者说是主题)并不知道订阅者的存在,而订阅者也不知道发布者的存在。他们彼此唯一的关系就是在调度中心注册成为订阅者或者发布者。

观察者模式

观察者(Observer)模式中包含两种对象,分别是目标对象和观察者对象。在目标对象和观察者对象间存在着一种一对多的对应关系,当这个目标对象的状态发生变化时,所有依赖于它的观察者对象都会得到通知并执行它们各自特有的行为。

区别

简单来讲,观察者模式是基于发布订阅模式的,发布订阅模式需要手动进行订阅和发布,是基于中间的调度栈进行的,可以不发布,也可以不订阅,发布订阅是解偶没有关联的,而观察者模式是有相互依赖关系的,并且观察者必须实现一个update方法提供调用。

发布订阅者模式示例

  • 如下,有两个异步获取文件的函数,在不使用promise的情况下,需要在读取到两个文件后执行finish。
js 复制代码
const fs = require('fs'); // 引入node中的fs模块
fs.readFile('./1.text', 'utf8', function (error, data) {
 	console.log('读取到了文件1.text'); 
});
fs.readFile('./2.text', 'utf8', function (error, data) {
 	console.log('读取到了文件2.text'); 
});
function finish() {
  console.log('文件读取完成');
}
  • 利用发布订阅模式,实现一个中间调度栈event
  • event需要缓存发布的数据的数据和订阅回调函数
  • event需要实现on和emit方法提供发布和订阅功能
    • on接收一个函数作为参数,并且将该函数进行缓存,等待发布消息后按顺序执行。
    • emit接收key和value两个参数,作为发布的键值对数据进行缓存,订阅函数被执行是传入。
js 复制代码
const event = {
  _arr: [], // 用于缓存所有订阅的回调函数
  data: {}, // 用于缓存发布的数据
  on(fn) {
    // 直接缓存订阅函数
    this._arr.push(fn);
  },
  emit(key, value) {
    // 发布数据,直接缓存数据并且执行所有的订阅函数。
    this.data[key] = value;
    this._arr.forEach(fn => fn(this.data));
  }
}
  • 最后使用该调度栈进行简单的发布订阅
js 复制代码
const fs = require('fs'); // 引入node中的fs模块
const event = {
  _arr: [], // 用于缓存所有订阅的回调函数
  data: {}, // 用于缓存发布的数据
  on(fn) {
    // 直接缓存订阅函数
    this._arr.push(fn);
  },
  emit(key, value) {
    // 发布数据,直接缓存数据并且执行所有的订阅函数。
    this.data[key] = value;
    this._arr.forEach(fn => fn(this.data));
  }
}

event.on((data) => { // 订阅
  console.log('当前读取到的文件', data);
});
event.on((data) => { // 订阅
  if (Reflect.ownKeys(data).length === 2) { // 等价于Object.Keys()
    finish();
  }
});

fs.readFile('./1.text', 'utf8', function (error, data) {
 	console.log('读取到了文件1.text'); 
  event.emit('text1', '1111'); // 发布
});
fs.readFile('./2.text', 'utf8', function (error, data) {
 	console.log('读取到了文件2.text'); 
  event.emit('text2', '2222'); // 发布
});
function finish() {
  console.log('文件读取完成');
  event.emit(); // 发布
}

观察者模式

  • 观察者模式分为观察者被观察者两个类。
  • 被观察者需要接收观察者。
  • 观察者需要提供update方法。
js 复制代码
// 被观察者
class Subject {
  constructor() {
    this.observers = []; // 用于接收观察者
    this.state = false; // 当前的被观察者状态
  }
  attach(fn) {
    this.observers.push(fn); // 订阅模式,被观察者接收观察者
  }
  setState(newValue) {
    this.state = newValue; // 修改状态
   	// 当状态变化时,需要通知所有观察者,调用观察者的update方法.
    this.observers.forEach(fn => fn.update(newValue));
  }
}

// 观察者
class Observer {
  update() {
    console.log('收到了通知!');
  }
}

const a = new Subject();
const b = new Observer();
const c = new Observer();
a.attach(o1); // 订阅
a.attach(o2); // 订阅

// 修改被观察者状态
a.setState(false);
相关推荐
爱敲代码的小鱼3 分钟前
Vue的简介:
前端·javascript·vue.js
H_ZMY18 分钟前
前端瀑布流布局:从基础实现到高性能优化全解析
前端·性能优化
jin42135221 分钟前
基于React Native鸿蒙跨平台一款阅读追踪应用完成进度条的增加与减少,可以实现任务的进度计算逻辑
javascript·react native·react.js·ecmascript·harmonyos
星夜落月22 分钟前
从零部署Wallos:打造专属预算管理平台
服务器·前端·网络·建站
qq_124987075326 分钟前
基于html的书城阅读器系统的设计与实现(源码+论文+部署+安装)
前端·vue.js·spring boot·后端·mysql·信息可视化·html
方安乐28 分钟前
react笔记之useLayoutEffect
javascript·笔记·react.js
cn_mengbei30 分钟前
React Native + OpenHarmony:useState延迟初始化
javascript·react native·react.js
新技术克36 分钟前
高级进阶 React Native 鸿蒙跨平台开发:NativeEventEmitter 原生事件发射器
javascript·react native·react.js·harmonyos
一个懒人懒人1 小时前
mysql2连接池配置与优化
前端·mysql