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

article/2025/10/27 0:25:00

观察者模式

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

观察者模式,指的是一个主题对象(subject),维护了一个依赖它的观察者(observers)数组,当subject变化的时候,会通知数组中的观察者自动更新它自己。
简单来说就是,一个对象(被观察者)的状态发生改变时,会通知所有依赖它的对象(观察者),这两者是直接关联的。

9d50837d41bf474c6ac4f0e62296b6e9.jpeg
如图所示,当Subject(被观察者)状态发生变化时,会给所有的Observers(观察者们)发送一个通知函数,观察者们接收到通知后通常会调用各自的更新函数。

/*** 悬赏任务*/
class Hunter {// 存储订阅的猎手需求demands = []constructor (name, intelligent, money) {this.name = name // 名字this.intelligent = intelligent // 职能this.money = money // 赏金}// 订阅subscribe (target, demand) {target.demands.push(demand)}// 发布publish (intelligent, money) {this.demands.forEach(demand => {demand(intelligent, money)})}
}
// 注册猎手
const a = new Hunter('张三', '前端开发', 5000)
const b = new Hunter('李斯', '后端开发', 5000)
const c = new Hunter('王五', '后端开发', 3000)
const boss = new Hunter('小明', '老板')
// 订阅老板
a.subscribe(boss, function(intelligent, money) {if (intelligent !== a.intelligent) {console.log('我是前端开发a,职能和我不匹配')return}if (money < a.money) {console.log('我是前端开发a,职能匹配,但是钱太少了不干')return}console.log('我是前端开发a, 职能和赏金都匹配')
})
b.subscribe(boss, function(intelligent, money) {if (intelligent !== b.intelligent) {console.log('我是后端开发b,职能和我不匹配')return}if (money < b.money) {console.log('我是后端开发b,职能匹配,但是钱太少了不干')return}console.log('我是后端开发b, 职能和赏金都匹配')
})
c.subscribe(boss, function(intelligent, money) {if (intelligent !== c.intelligent) {console.log('我是后端开发c,职能和我不匹配')return}if (money < c.money) {console.log('我是后端开发c,职能匹配,但是钱太少了不干')return}console.log('我是后端开发c, 职能和赏金都匹配')
})
// 老板发布悬赏
boss.publish('后端开发', 3000)
// 我是前端开发a,职能和我不匹配
// 我是后端开发b,职能匹配,但是钱太少了不干
// 我是后端开发c, 职能和赏金都匹配

发布订阅模式

发布订阅模式中,发布者发布消息时不会将消息直接发送给订阅者,发布者和订阅者之间不存在直接的联系;在发布者和订阅者之间存在第三方平台,称为消息代理或调度中心或中间件,它维持着发布者和订阅者之间的联系,可以处理所有发布者发布的消息并将它们分发给对应的订阅者,实现了发布者与订阅者之间的解耦。

发布-订阅是一种消息范式,消息的发送者(publisher)不会将消息直接发送给特定的接收者(subcriber)。而是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话)可能存在。同样的,订阅者可以表达对一个或多个类别的兴趣,只接收感兴趣的消息,无需了解哪些发布者(如果有的话)存在。

5241362-3b0edd9d6de0df1b.png
如图所示,发布者与订阅者之间不是互相依赖和关联的,两者之间有一个通信结构(事件通道)。这个事件通道会处理发布者发布的不同类型的通知,并且将这些通知发送给相应的订阅者。

/*** 找年龄相同的人*/
// 调度中心
class Topic {static demands = {}// 订阅所有需求static subscribe (key, demand) {// 对需求分类收集if (!Topic.demands[key]) Topic.demands[key] = []Topic.demands[key].push(demand)}// 对所有订阅者发布通知static publish (key, age) {if (!Topic.demands[key]) returnfor (const demand of Topic.demands[key]) {demand(age)}}
}
// 找对象的猎手类
class Hunter {constructor (name, age) {this.name = name // 名字this.age = age // 年龄}// 订阅,由调度中心将猎手需求分类并存放到全局subscribe (key, demand) {Topic.subscribe(key, demand)}// 发布,由调度中心将同分类下的需求全部触发publish (key, age) {Topic.publish(key, age)}
}
// 猎手注册
const aa = new Hunter('aa', 18)
const bb = new Hunter('bb', 20)
// 猎手订阅自己感兴趣的人
aa.subscribe('key', function (age) {if (age === aa.age) console.log(`我是aa,我们都是${age}`)else console.log(`我是aa,我们年龄不同`)
})
bb.subscribe('key', function (age) {if (age === bb.age) console.log(`我是bb,我们都是${age}`)else console.log(`我是bb,我们年龄不同`)
})
// 红娘注册
const red = new Hunter('red', 35)
// 红娘发布信息
red.publish('key', 20)
// 我是aa,我们年龄不同
// 我是bb,我们都是20

观察者模式和发布订阅模式的区别

alt
1.在观察者模式中,观察者是知道Subject的,Subject一直保持对观察者进行记录。然而,在发布订阅模式中,发布者和订阅者不知道对方的存在。它们只有通过消息代理进行通信。
2.在发布订阅模式中,组件是松散耦合的,正好和观察者模式相反。
3.观察者模式大多数时候是同步的,比如当事件触发,Subject就会去调用观察者的方法。而发布-订阅模式大多数时候是异步的(使用消息队列)。
4.观察者 模式需要在单个应用程序地址空间中实现,而发布-订阅更像交叉应用模式。尽管它们之间有区别,但有些人可能会说发布-订阅模式是观察者模式的变异,因为它们概念上是相似的。


在这里插入图片描述


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

相关文章

redis发布订阅模式详解

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

Vue发布订阅模式

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

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

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

C++发布订阅模式

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

Java实现发布订阅模式

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

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

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

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

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

发布-订阅模式

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

什么是发布订阅模式?

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

发布订阅模式

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

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

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

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

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

Smobiler 仿得到APP个人主页

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

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

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

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

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

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

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

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

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

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

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

Smobiler实现手机弹窗

前言 在实际项目中有很多场景需要用到弹窗&#xff0c;如图1 那么这些弹窗在Smobiler中如何实现呢&#xff1f; 正文 Smobiler实现弹窗有两种方式&#xff1a;1.MessageBox.Show 2.ShowDialog和ShowContextDialog。前者适合简易弹窗&#xff0c;后者适合自定义弹窗。 Messa…

Smobiler实现美观登录界面——C# 或.NET Smobiler实例开发手机app(二)

目录 一、 本文目标 二、 准备工作 1、 数据库 2、 材料 三、 界面布局 1、设置控件的属性值 &#xff08;1&#xff09; 输入框 &#xff08;2&#xff09; 图片属性 &#xff08;3&#xff09; HandElectricity的标题的label属性 &#xff08;4&#xff09;登录按钮…