观察者模式

当对象之间存在一对多的依赖关系时,其中一个对象的状态发生改变,所有依赖它的对象都会收到通知,这就是观察者模式。

在观察者模式中,只有两种主体:目标对象 (Subject) 和 观察者 (Observer)。

  • 目标对象 Subject:

    • 维护观察者列表 observerList ———— 维护拥有订阅权限的用户列表
    • 定义添加观察者的方法 ———— 提供用户订阅权限的功能
    • 当自身发生变化后,通过调用自己的 notify 方法依次通知每个观察者执行 update 方法 ———— 发布对应任务后通知有订阅权限的用户
  • 观察者 Observer 需要实现 update 方法,供目标对象调用。update方法中可以执行自定义的业务逻辑 ———— 定义接收任务通知后的方法。

class Subject {constructor() {this.observerList = [];}add(observer) {this.observerList.push(observer);}remove(observer) {this.observerList = this.observerList.filter(item => item !== observer)}notify(...args) {this.observers.forEach(observer => observer.update(...args));}
}// 观察者
class Observer {update(...args) {console.log(...args);}
}// 创建观察者ob1
let ob1 = new Observer();
// 创建观察者ob2
let ob2 = new Observer();
// 创建目标sub
let sub = new Subject();
// 目标sub添加观察者ob1 (目标和观察者建立了依赖关系)
sub.add(ob1);
// 目标sub添加观察者ob2
sub.add(ob2);
// 目标sub触发SMS事件(目标主动通知观察者)
sub.notify('I fired `SMS` event', 'heelp');

发布订阅者模式

基于一个事件(主题)PubSub 通道,希望订阅者 subscriber 通过自定义事件 subscribe 订阅主题。发布者publisher 通过 publish 发布主题事件的方式通知各个订阅该主题的 Subscriber 对象。

因此发布订阅模式与观察者模式相比,发布订阅模式中有三个角色,发布者 Publisher ,事件调度中心 Event Channel ,订阅者 Subscriber

上面的文字有些难以理解,在现在的发布订阅模式中,称为发布者的消息发送者不会将消息直接发送给订阅者,这意味着发布者和订阅者不知道彼此的存在。在发布者和订阅者之间存在第三个组件,称为调度中心或事件通道,它维持着发布者和订阅者之间的联系,过滤所有发布者传入的消息并相应地分发它们给订阅者。

  • 任务发布者 —— Publisher

  • 事件中心 —— PubSub

    • 维护任务类型 subscribers 对象,以及每种任务下的订阅情况
    • 给订阅者提供订阅功能 —— subscribe 功能
    • 给发布者的提供发布任务 —— publish 功能
  • 订阅者 —— Subscriber

举一个例子,你在微博上关注了A,同时其他很多人也关注了A,那么当A发布动态的时候,微博就会为你们推送这条动态。A就是发布者,你是订阅者,微博就是调度中心,你和A是没有直接的消息往来的,全是通过微博来协调的(你的关注,A的发布动态)。

class PubSub {constructor() {this.subscribers = {};}// 订阅subsctibe(topic, cb) {if (!this.subscribers[topic]) {this.subscribers[topic] = []}this.subscribers[topic].push(cb)}// 取消订阅unsubsctibe(topic, cb) {let temp = this.subscribers[topic]if (temp) {let index = temp.findIndex(item => item === cb)temp.splice(index, 1)}}// 发布功能publish(topic, ...args) {if (this.subscribers[topic]) {this.subscribers[topic].forEach(cb => cb(...args))}}
}let clg = function(text) {console.log(text)
}// 创建事件调度中心,为订阅者和发布者提供调度服务
let pubSub = new PubSub();
// A订阅了SMS事件(A只关注SMS本身,而不关心谁发布这个事件)
pubSub.subscribe('SMS', clg);
// B订阅了SMS事件
pubSub.subscribe('SMS', clg);
console.log(pubSub.subscribers)
// C发布了SMS事件(C只关注SMS本身,不关心谁订阅了这个事件)
pubSub.publish('SMS', 'I published `SMS` event');

从代码实现可以看出,观察者模式则是面向目标和观察者编程的,而发布-订阅模式是面向调度中心编程的,前者用于耦合目标和观察者,后者用于解耦发布者和订阅者,不可同日而语也~

JavaScript设计模式:观察者模式与发布订阅者模式实现相关推荐

  1. EventBus—思考观察者模式与发布订阅者模式

    EventBus系列文章: EventBus-使用实践 EventBus-源码解析 1. 概述 EventBus是基于发布订阅者模式的消息处理框架. EventBus is an open-sourc ...

  2. 2.设计模式-观察者模式(发布-订阅模式)

    观察者模式(发布-订阅模式)一个简单的使用 简介 例子 被监听者(被观察者) 监听者(观察者) 测试类 简介 观察者模式(有时又被称为模型(Model)-视图(View)模式.源-收听者(Listen ...

  3. JS设计模式 - 观察者模式与发布/订阅模式

    观察者模式本质上是一种对象行为模式,而 发布/订阅模式本质上是一种架构模式,强调组件的作用. 1. 观察者模式 观察者模式是一种设计模式,其中一个对象(称为主体)根据对象(观察者)维护一个对象列表,自 ...

  4. js观察者模式和发布订阅者模式

    一.观察者模式的理解 观察者模式:一个对象(称为subject)维持一系列依赖于它的对象(称为observer),将有关状态的任何变更自动通知给它们(观察者). 二.发布/订阅模式的理解 发布/订阅模 ...

  5. Vue观察者模式和发布订阅者模式

    什么是观察者模式? 例如:抖音上的小杨哥,当小杨哥在抖音开启直播时,会自动通知所有的粉丝. 小杨哥:直播间开播了! 小杨哥为目标   抖友为观察者 目标应该具备 收集观察者 删除观察者 通知观察者 & ...

  6. JavaScript 设计模式之观察者模式与发布订阅模式

    前言 在软体工程中,设计模式(design pattern)是对软体设计中普遍存在(反复出现)的各种问题,所提出的解决方案. 设计模式并不直接用来完成程式码的编写,而是描述在各种不同情况下,要怎么解决 ...

  7. 游戏服务器架构-设计模式之观察者模式和发布订阅模式真的一样吗?

    前面我给大家分享了观察者模式和发布订阅模式,有人私信给我说这俩不是一样嘛,大体没什么区别,我猜测大多数认为这两者是一样的可以继续阅读这两篇文章,如果还不能解答你的问题,我相信这篇文章对比两者的关系会让 ...

  8. js设计模式之观察者模式和发布/订阅模式

    观察者模式 The Observer is a design pattern where an object (known as a subject) maintains a list of obje ...

  9. JavaScript设计模式 -发布订阅者模式

    1. 定义 发布订阅者模式又叫观察者模式,他定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得将得到通知 案例: 小明最近看上了一套房子,到了售楼处之后才被告知,该楼 ...

最新文章

  1. ldap 统一认证 java_如何在你的系统里集成LDAP统一认证
  2. 【转】mysqldump的锁表的问题
  3. ext中给文本框赋值的方法_大多数人不知道的Python合并字典的七种方法
  4. Ubuntu18.04安装Multiwfn
  5. 我的2017年文章汇总——Java及中间件篇
  6. 百练OJ:2713:肿瘤面积
  7. 解决android中出现的无法加载library的问题
  8. SpringMVC工作原理 1
  9. Android系统充电系统介绍-预防手机充电爆炸
  10. 泛型之类型擦除和桥接方法
  11. (80)Verilog HDL测试激励:保存波形文件
  12. mysql invalid default value_mysql5.x升级到5.7 导入数据出错,提示Invalid default value for...
  13. html5画布作品,HTML5 canvas画布
  14. javamailsender注入失败_Springboot 之 JavaMailSender发送电子邮件
  15. CentOS6_mini_安装后基本配置
  16. 基本排序算法之1——希尔排序shellsort
  17. getrusage-进程资源统计函数
  18. 安卓-控制台-和风天气,和风天气3.0使用方法
  19. aws lambda_借助AWS Elastic Beanstalk轻松进行Spring Boot部署
  20. JVM调优参数大全及G1GC调优

热门文章

  1. 圆柱体类的java写法,JavaFX圆柱体
  2. 倍福100W电机和200W电机型号选择
  3. 盘点让新加坡人骄傲的十大品牌!来新加坡必买必逛!
  4. oracle数据库学习总结
  5. 微信小程序-利用wxs脚本实现姓名、手机号、身份证号中间带星显示
  6. 英语介词短语的句法功能
  7. 2020年ai顶会时间表_2020年企业采用AI
  8. linux下的安装命令行工具下载,本地安装DEB包的3种命令行工具(适合Debian体系)
  9. 三国志11原版win11成功运行心得
  10. 简单实现中文分词中的常用字过滤