JavaScript设计模式:四、发布订阅模式

article/2025/10/27 0:26:24

JavaScript设计模式:四、发布订阅模式

文章目录

  • JavaScript设计模式:四、发布订阅模式
    • 一、概述
      • 1. 观察者模式
      • 2. 发布订阅模式
      • 3. 观察者模式是不是发布订阅模式

一、概述

观察者模式: 观察者(Observer)直接订阅(Subscribe)主题(Subject),而当主题被激活的时候,会触发(Fire Event)观察者里的事件。

发布订阅模式: 订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Topic),当发布者(Publisher)发布该事件(Publish topic)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码。
在这里插入图片描述

1. 观察者模式

  1. 首先定义一个数组存储订阅列表(数组存函数)
  2. 定义订阅函数,函数参数:订阅对象与订阅信息。函数体负责将订阅信息(为一个函数)存入订阅数组列表。
  3. 定义发布任务函数,函数接受订阅信息参数。函数体内遍历订阅信息,以遍能够找到匹配的订阅信息。

主要维护一个存储函数的数组,通过入栈的方式维护订阅信息,通过数组遍历的方式使用订阅列表,以找到匹配的订阅信息。

function Hunter(name, level) {this.name = name;this.level = level;this.list = [];
}
Hunter.prototype.publish = function(money) {console.log(this.level + '猎人' + this.name + '寻求帮助');this.list.forEach(function(item, index) {item(money);})
}
Hunter.prototype.subscribe = function(target, fn) {console.log(this.level + '猎人' + this.name + '订阅了' + target);target.list.push(fn); // 向目标猎人list中推入订阅
}
let hounterMing = new Hunter('小明','黄金');
let hounterJin = new Hunter('小金','黄金');
let hounterZhang = new Hunter('校长', '黄金');
let hounterPeter = new Hunter('Peter', '黄铜');hunterMing.subscribe(hunterPeter, function(money){console.log('小明表示:' + (money > 200 ? '' : '暂时很忙,不能') + '给予帮助')
})
hunterJin.subscribe(hunterPeter, function(){console.log('小金表示:给予帮助')
})
hunterZhang.subscribe(hunterPeter, function(){console.log('小金表示:给予帮助')
})
hunterPeter.publish(198)

2. 发布订阅模式

观察者模式和发布订阅模式最大的区别就是发布订阅模式有个事件调度中心。

观察者模式由具体目标调度,每个被订阅的目标里面都需要有对观察者的处理,这种处理方式比较直接粗暴,但是会造成代码的冗余。

而发布订阅模式中统一由调度中心进行处理,订阅者和发布者互不干扰,消除了发布者和订阅者之间的依赖。这样一方面实现了解耦,还有就是可以实现更细粒度的一些控制。比如发布者发布了很多消息,但是不想所有的订阅者都接收到,就可以在调度中心做一些处理,类似于权限控制之类的。还可以做一些节流操作。

通俗版本:

  1. 发布订阅模式就是将原本属于被订阅者维护的订阅列表独立出来,增加了一个专门处理订阅信息的订阅中心。实际上依然是维护一个数组列表。
  2. 发布者和订阅者的发布和订阅的具体内部逻辑被订阅中心接管,只需要调用订阅中心的函数即可。
/*** HunterUnion 负责任务函数的存储,实现形式为对象数组的入栈和遍历。* 内部数据结构为 :* topics: {*   'tiger1': [functionA(), functionB, function C],*   'tiger2': [functionA(), functionB, function C],* }*/
let HunterUnion = {type: 'hunt',topics: Object.create(null),subscribe: function (topic, fn){if(!this.topics[topic]){this.topics[topic] = [];  }this.topics[topic].push(fn);},publish: function (topic, money){if(!this.topics[topic])return;for(let fn of this.topics[topic]){fn(money)}}
}// Hunter只负责存储基本的订阅信息
function Hunter(name, level) {this.name = name;this.level = level;
}Hunter.prototype.subscribe = function(topic, fn) {console.log(this.level + '猎人' + this.name + '订阅了狩猎' + topic + '的任务');HunterUnion.subscribe(topic, fn);
}
Hunter.prototype.publish = function(topic, money) {console.log(this.level + '猎人' + this.name + '发布了狩猎' + topic + '的任务');HunterUnion.publish(topic, money);
}//猎人工会走来了几个猎人
let hunterMing = new Hunter('小明', '黄金')
let hunterJin = new Hunter('小金', '白银')
let hunterZhang = new Hunter('小张', '黄金')
let hunterPeter = new Hunter('Peter', '青铜')hunterMing.subscribe('tiger', function(money){console.log('小明表示:' + (money > 200 ? '' : '不') + '接取任务')
})
hunterJin.subscribe('tiger', function(money){console.log('小金表示:接取任务')
})
hunterZhang.subscribe('tiger', function(money){console.log('小张表示:接取任务')
})
//Peter订阅了狩猎sheep的任务
hunterPeter.subscribe('sheep', function(money){console.log('Peter表示:接取任务')
})//Peter发布了狩猎tiger的任务
hunterPeter.publish('tiger', 198)

3. 观察者模式是不是发布订阅模式

网上关于这个问题的回答,出现了两极分化,有认为发布订阅模式就是观察者模式的,也有认为观察者模式和发布订阅模式是真不一样的。

其实我不知道发布订阅模式是不是观察者模式,就像我不知道辨别模式的关键是设计意图还是设计结构(理念),虽然《JavaScript设计模式与开发实践》一书中说了分辨模式的关键是意图而不是结构。

如果以结构来分辨模式,发布订阅模式相比观察者模式多了一个中间件订阅器,所以发布订阅模式是不同于观察者模式的;如果以意图来分辨模式,他们都是实现了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,并自动更新,那么他们就是同一种模式,发布订阅模式是在观察者模式的基础上做的优化升级。

不过,不管他们是不是同一个设计模式,他们的实现方式确实有差别,我们在使用的时候应该根据场景来判断选择哪个。


http://chatgpt.dhexx.cn/article/m1688rBL.shtml

相关文章

发布订阅模式理解

发布订阅模式理解 1.发布-订阅模式 发布订阅模式是一种一对多的对象对应关系,多个观察者同时监听某一个对象,当该对象发生改变时,就会执行一个发布事件,这个发布事件会通知所有的事件订阅者,事件订阅者根据得到的数据…

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

观察者模式 观察者模式在前端工程中是很常见的设计模式,因为前端交互中充斥着大量多控件联动的交互,当参与联动的组件数量比较多或者组件数量可能变化的时候,代码就会变得难以维护。但是如果我们写代码时遵循了观察者模式的设计,…

redis发布订阅模式详解

文章目录 写在前面发布订阅的使用SUBSCRIBE命令PUBLISH命令注意发布、订阅客户端启动顺序! PUBSUB命令PUNSUBSCRIBE命令UNSUBSCRIBE命令PSUBSCRIBE命令 总结 写在前面 Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订…

Vue发布订阅模式

简单的来说一下在别人问你这个问题的时候怎么来回答它 前端新人,如有错误求大佬指出~求教💝 情景复现 大佬提问:“你知道Vue发布订阅模式是什么吗?" 我的回答:“发布订阅模式其实是一种对象间一对多的依赖关系&…

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

一、概念 观察者(Observer),又称发布-订阅(Publish-Subscrice),属于23中设计模式之一。 发布订阅模式定义了一种一对多的依赖关系,让多个订阅者对象同时监听某一个主题对象。这个主题对象在自身状态变化时&#xff0c…

C++发布订阅模式

C发布订阅模式 发布订阅模式主要包含三个部分:消息发布、消息订阅者、消息处理中心。与观察者模式相比多出了消息处理中心模块,这样在结构上可以解耦订阅者与发布者,功能上更加的丰富。 观察者模式 结构设计 有一个消息list,主…

Java实现发布订阅模式

什么是发布订阅模式 发布订阅模式是软件开发者很常见的一种设计模式,很多开源库都使用了发布订阅模式,例如RxJava、EventBus、Vue等,所以学习该模式还是很有必要的。 该模式中存在一个或多个发布者,一个或多个订阅者&#xff0c…

设计模式 —— 发布订阅模式

设计模式 —— 发布订阅模式 《工欲善其事,必先利其器》 我在之前有写过一篇关于 《观察者模式》 的文章,大家有兴趣的可以去看看,个人认为那个例子还是挺生动的。(狗头) 不过今天我们要学习的是,发布订阅…

小侃设计模式(十八)-发布订阅模式

1.概述 发布订阅模式又叫观察者模式(Observer Pattern),它是指对象之间一对多的依赖关系,每当那个特定对象改变状态时,所有依赖于它的对象都会得到通知并被自动更新,它是行为型模式的一种。观察者模式内部…

发布-订阅模式

发布-订阅模式 学习知识要善于思考,思考,再思考。 —— 爱因斯在众多设计模式中,可能最常见、最有名的就是发布 - 订阅模式了,本篇我们一起来学习这个模式。 发布 - 订阅模式 (Publish-Subscribe Pattern, pub-sub&a…

什么是发布订阅模式?

发布-订阅模式(Publish-Subscribe pattern)是一种软件架构模式,用于实现组件之间的解耦和消息传递。在这种模式中,组件(发布者)将消息发送到一个中心(消息代理或主题),然…

发布订阅模式

零、目录 应用场景实现原理代码实现全局模式下的订阅发布模式(泛化的订阅发布模式)总结 一、应用场景 ​ 发布订阅模式,广泛的存在于在我们的生活之中。 ​ 举个一个简单的例子来说,当我们在浏览视频或者博客论坛之类的网…

.NET(C#、VB)APP开发——Smobiler平台控件介绍:VLCPlayer

本文简述如何在Smobiler中使用VLCPlayer插件,该插件支持播放rtsp流。 Step 1. 新建一个SmobilerForm窗体,再拖入VLCPlay,布局如下 在设计器中给VLCPlayer.Url赋值或者在窗体的Load事件中赋值 演示使用的rtsp流地址 rtsp://wowzaec2demo.strea…

.NET(C#、VB)APP开发——Smobiler平台控件介绍:TTS

本文简述如何在Smobiler中使用TTS文字转语音。 Step 1. 新建一个SmobilerForm窗体,并在窗体中加入TTS和Button,布局如下 Button的点击事件代码: private void button1_Press(object sender, EventArgs e){ //第一个参数为文本;第…

Smobiler 仿得到APP个人主页

原型如下: 完整代码参考 https://github.com/comsmobiler/BlogsCode/blob/master/Source/BlogsCode_SmobilerForm/MyForm/dedao.cs 思路 可以将原型按照上图分成2个部分,部分A可以使用label、image、button、imagebutton、fontIcon控件来实现&#xff…

.NET(C#、VB)APP开发——Smobiler平台控件介绍:PDFView

本文简述如何在Smobiler中使用PDFView。 Step 1. 新建一个SmobilerForm窗体,再拖入PDfView,布局如下 PDFView.ResourcrPath默认Document,指项目下\Resources\Document,若是pdf文件放在该文件夹下,则在设计器中直接赋值…

.NET(C#、VB)APP开发——Smobiler平台控件介绍:OCR组件

本文简述如何在Smobiler中使用OCR组件进行文字识别。 Step 1. 新建一个SmobilerForm窗体,并在窗体中加入OCR和Button,布局如下 Button的点击事件代码: private void button1_Press(object sender, EventArgs e){ocr1.Recognize((obj,args)>…

.NET(C#、VB)APP开发——Smobiler平台控件介绍:ArcFace人脸识别

本文简述如何在Smobiler中使用ArcFace(虹软人脸识别)。 Step 1. 新建一个SmobilerForm窗体,再拖入Button,Label,TextBox和AcrFace,布局如下 在设计器中给MediaView.Url赋值或者在窗体的Load事件中赋值 Button的事件代码如下 string message …

移动OA办公——Smobiler第一个开源应用解决方案,快来get吧

产品简介 SmoONE是一款移动OA类的开源解决方案,通过Smobiler平台开发,包含了注册、登陆、用户信息等基本功能。集成了OA中使用场景较多的报销、请假、部门管理、成本中心等核心功能。 免费获取方案 开源代码:https://github.com/comsmobile…

.NET(C#、VB)APP开发——Smobiler平台控件介绍:UsbSerial串口通讯组件

本文简述如何在Smobiler中使用UsbSerial。 Step 1. 新建一个SmobilerForm窗体,再拖入UsbSerial和Button,布局如下 按钮事件代码: //连接private void button1_Press_2(object sender, EventArgs e){usbSerial1.Connect(Smobiler.Plugins.USBS…