理解JavaScript 的发布者/订阅者模式

什么是发布者/订阅者模式

发布者-订阅者模式是一种软件设计模式,用于实现对象之间的一对多依赖关系。在这种模式中,一个对象(被称为发布者)而其他对象(成为订阅者)可以在发布者上注册自己,以接受特定事件或消息的通知。

发布者: 负责维护订阅者列表和发布事件或消息。当某个事件或消息发生时,发布者将通知发送给所有订阅者。
订阅者:注册在发布者上,以接受感兴趣的事件或消息的通知。当发布者发布相应事件时,订阅者相应做出响应。
工作流程:

  1. 发布者维护一个订阅者列表,并提供注册、注销和通知的方法。
  2. 订阅者注册自己到发布者上,表明自己对某个事件或消息感兴趣。
  3. 当发布者发布相应的事件或消息时,会遍历订阅者列表,将通知发送给所有订阅者。
  4. 订阅者收到通知后,执行相应的处理逻辑。
    优点:
  • 实现了松耦合:发布者和订阅者之间相互独立,可以方便的删除和增加订阅者,而不影响其他代码部分。
  • 提高代码复用性:多个订阅者可以共享同一个发布者,在这里插入代码片从而实现代码的复用。
    应用场景:
  • GUI应用程序中的事件处理机制。
  • 前端框架中的监听和消息通知。
  • JS中的自定义事件。

结合例子理解:

// 发布者 (Publisher/Subject)
class Publisher {constructor() {this.subscribers = [];}// 注册订阅者subscribe(subscriber) {this.subscribers.push(subscriber);}// 取消订阅unsubscribe(subscriber) {this.subscribers = this.subscribers.filter((sub) => sub !== subscriber);}// 发布事件通知publish(message) {this.subscribers.forEach((subscriber) => subscriber.receive(message));}
}// 订阅者 (Subscriber/Observer)
class Subscriber {constructor(name) {this.name = name;}// 接收事件通知receive(message) {console.log(`${this.name} received: ${message}`);}
}// 创建发布者实例
const publisher = new Publisher();// 创建订阅者实例
const subscriberA = new Subscriber('Subscriber A');
const subscriberB = new Subscriber('Subscriber B');// 订阅者注册到发布者上
publisher.subscribe(subscriberA);
publisher.subscribe(subscriberB);// 发布者发布事件通知
publisher.publish('Hello World!');// 取消订阅者A的订阅
publisher.unsubscribe(subscriberA);// 再次发布事件通知
publisher.publish('How are you?');

在这个例子中,创建了一个简单的发布者类Publisher和一个订阅者类Subscriber。发布者维护一个订阅者列表,并提供subscribe方法用于注册订阅者,unsubscribe用于取消订阅,publish方法用于发布事件通知。
输出结果:

Subscriber A received: Hello World!
Subscriber B received: Hello World!
Subscriber B received: How are you?

在输出结果中,可以看到订阅者A和订阅者B都收到了 “Hello World!” 的事件通知。然后取消了订阅者A的订阅,再次发布事件通知时,
只有订阅者B收到了 “How are you?” 的事件通知。这展示了发布者-订阅者模式的工作机制:多个订阅者可以订阅同一个发布者,
发布者发布事件通知时,所有订阅者都会收到相应的通知。同时,订阅者可以根据自己的需求注册和取消订阅,从而实现灵活的事件处理。

观察者模式

实际上,发布者-订阅者模式和观察者模式是同一种模式,只是在不同的文献或资料中可能称呼不同。

在发布者-订阅者模式中,有一个调用中心(或者称为发布者或主题),它负责维护订阅者列表和发布事件或消息。
其他对象(订阅者或观察者)可以注册自己到调用中心,以接收特定事件或消息的通知。
需要注意的是,虽然两种模式的概念相似,但在具体实现上可能有一些差异。
不同的开发框架或库可能有不同的实现方式,但总体的思想和目标都是相同的。选择使用哪种模式取决于具体的应用场景和需求。
用观察者模式举个例子:

// 被观察者 (Subject)
class Subject {constructor() {this.observers = [];}// 注册观察者addObserver(observer) {this.observers.push(observer);}// 注销观察者removeObserver(observer) {this.observers = this.observers.filter((obs) => obs !== observer);}// 发送通知给所有观察者notify(message) {this.observers.forEach((observer) => observer.update(message));}
}// 观察者 (Observer)
class Observer {constructor(name) {this.name = name;}// 接收通知update(message) {console.log(`${this.name} received: ${message}`);}
}// 创建被观察者实例
const subject = new Subject();// 创建观察者实例
const observerA = new Observer('Observer A');
const observerB = new Observer('Observer B');// 观察者注册到被观察者上
subject.addObserver(observerA);
subject.addObserver(observerB);// 被观察者发送通知
subject.notify('Hello World!');// 观察者注销
subject.removeObserver(observerA);// 再次发送通知
subject.notify('How are you?');

输出结果与之前的发布者-订阅者模式相同:

Observer A received: Hello World!
Observer B received: Hello World!
Observer B received: How are you?

总结

在实际开发中,无论是使用观察者模式还是订阅者-发布者模式,它们的基本思想和用法是相同的:一个对象(被观察者或发布者)维护一个观察者列表,其他对象(观察者或订阅者)可以注册自己到这个列表中,以接收特定事件或消息的通知。当事件或消息发生时,被观察者或发布者会遍历观察者列表,将通知发送给所有观察者或订阅者。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/10275.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

本地文件夹上传到Github

本地文件夹上传到Github 步骤1. 下载git步骤2. 在github中新建一个库(Repository)步骤3. 设置SSH key步骤4. 添加SSH keys步骤5. 本地文件上传到github参考 步骤1. 下载git 下载git客户端,并在本地安装完成。 步骤2. 在github中新建一个库&a…

Install Ansible on CentOS 8

环境准备: 1.至少俩台linux主机,一台是控制节点,一台是受控节点 2.控制节点和受控节点都需要安装Python36 3.控制节点需要安装ansible 4.控制节点需要获得受控节点的普通用户或root用户的权限,控制节点需要ssh客户端,…

HTTPS工作原理

先简述一下什么是HTTPS,HTTPS就是在HTTP的基础上增加了SSL/TLS来完成加密传输,以免敏感信息被第三方获取,所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。 一、客户端发起HTTPS请求 这个没什么好说的,就是…

windows和linux中查找文档中的特定字符

一、windows上,使用find命令。 语法:findstr [参数] [字符串] [磁盘:[目录]文件] findstr [/v] [/n] [/i] [/offline] “string” [[drive:][path]filename[ …]] 参数说明: /b 如果位于行的开头则匹配模式。 /e …

lil_matrix()

看代码的时候遇到的,简单记录记录一下。 这是一种用于逐步构建稀疏矩阵的结构(官方文档中写的),换句话说这是一种存储稀疏矩阵的方式。该稀疏矩阵通过两个list存储: rows [list([ ]) list([ ]) list([ ]) ... list(…

【C#】类的赋值是引用

在C#中,类的赋值是将一个类的实例赋给另一个类的实例或者将一个类的实例赋给一个变量。 例如,假设有一个名为Person的类: csharp public class Person { public string Name { get; set; } public int Age { get; set; } } 然后可以创建两个…

[JavaScript游戏开发] 绘制冰宫宝藏地图、人物鼠标点击移动、障碍检测

系列文章目录 第一章 2D二维地图绘制、人物移动、障碍检测 第二章 跟随人物二维动态地图绘制、自动寻径、小地图显示(人物红点显示) 第三章 绘制冰宫宝藏地图、人物鼠标点击移动、障碍检测 文章目录 系列文章目录前言一、本章节效果图二、介绍2.1、准备地图素材2.2、封装地图上…

[OnWork.Tools]系列 01-简介

说明 OnWork.Tools 是基于 Net6 的桌面程序。支持Windows7SP1及以上系统,主要是日常办公或者是开发工作过程中常用的工具集合。界面使用WPF Mvvm模式开发,目的是将开源项目中,好用的项目集成到一起,方便大家使用和学习。 功能 …

React:从 npx开始

使用 npm 来创建第一个 recat 文件( react-demo 是文件名,可以自定义) npx create-react-app react-demo npx是 npm v5.2 版本新添加的命令,用来简化 npm 中工具包的使用 原始: 全局安装npm i -g create-react-app 2 …

thinkphp 用户登录记录日记

<?phpnamespace app\api\model;use think\Model;class OperateLog extends Model {// 唯一键protected $pk id;protected $table operate_log;public static function log($data){return self::create($data, true);} }model <?phpnamespace app\admin\model;use ap…

ChatGPT漫谈(二)

ChatGPT“脱胎”于OpenAI在2020年发布的GPT-3,任何外行都可以使用GPT-3,在几分钟内提供示例,并获得所需的文本输出。GPT-3被认为是当时最强大的语言模型,但现在,ChatGPT模型似乎更强大。ChatGPT能进行天马行空的长对话,可以回答问题,它具备了类人的逻辑、思考与沟通的能…

【Matter】基于Ubuntu 22.04 编译chip-tool工具

前言 编译过程有点曲折&#xff0c;做下记录&#xff0c;过程中&#xff0c;有参考别人写的博客&#xff0c;也看github 官方介绍&#xff0c;终于跑通了~ 环境说明&#xff1a; 首先需要稳定的梯子&#xff0c;可以访问“外网”ubuntu 环境&#xff0c;最终成功实验在Ubunt…

组合API

组合API 1. 为什么要引入组合API2. setup()函数3. 响应式API3.1 reactive和watchEffect3.2 ref3.3 readonly3.5 watch 4. 生命周期钩子5. 依赖注入6. 逻辑提取和重用7. 小结 1. 为什么要引入组合API 组合API是Vue 3中引入的一种新的编程模式&#xff0c;它将组件的逻辑分散到多…

Linux 下centos 查看 -std 是否支持 C17

实际工作中&#xff0c;可能会遇到c的一些高级特性&#xff0c;例如std::invoke&#xff0c;此函数是c17才引入的&#xff0c;如何判断当前的gcc是否支持c17呢&#xff0c;这里提供两种办法。 1.根据gcc的版本号来推断 gcc --version&#xff0c;可以查看版本号&#xff0c;笔者…

数据结构【线性表】

数据结构入门级 第二章 线性表 一、线性表的定义和基本操作 线性表的定义&#xff1a;具有相同属性数据类型的数据元素组成的一个有限序列&#xff1b;除第一个元素外的元素都有直接前驱&#xff0c;除最后一个元素外的元素都有直接后继&#xff1b;存在一个唯一被称为“第一个…

从简单线性回归到TensorFlow深度学习

大家好&#xff0c;人工智能近年来变得越来越流行&#xff0c;学习人工智能的需求也随之增加&#xff0c;尤其是许多IT专业人士希望利用机器学习的强大功能&#xff0c;但面临不小的挑战&#xff0c;尤其是在理论和数学上。 步骤1&#xff1a;线性回归 线性回归是一种统计学中…

lucene、solr、es的区别以及应用场景

目录 1. Lucene:2. Solr:3. Elasticsearch: Lucene、Solr 和 Elasticsearch(ES) 都是基于 Lucene 引擎的搜索引擎&#xff0c;它们之间有相似之处&#xff0c;但也有一些不同之处。 Lucene 是一个低级别的搜索引擎库&#xff0c;它提供了一种用于创建和维护全文索引的 API&…

RNN架构解析——GRU模型

目录 GRU模型实现优点和缺点 GRU模型 实现 优点和缺点

【C语言day06】

逻辑或运算如果前表达式为真&#xff0c;后表达式不计算&#xff0c;第一次循环时i为0&#xff0c;执行i&#xff0c;第二次循环时i为1&#xff0c;是个真值&#xff0c;不再执行i&#xff0c;也就死循环了 在C语言中&#xff0c;一个函数如果不写返回值类型&#xff0c;那么就…

【MyBatis 学习三】子段不一致问题 多表查询 动态SQL

目录 一、解决Java实体类属性与数据库表字段不一致问题 &#x1f337;现象1&#xff1a;显示字段不对应&#xff1a;使用ResultType查询结果为null&#xff1b; &#x1f337;解决办法&#xff1a;字段不对应&#xff1a;使用ResultMap解决。 二、数据库的多表查询 &#…