观察者模式VS发布订阅模式区别

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

观察者模式VS发布订阅模式区别

观察者模式:订阅者收集函数,发布者循环调用
发布订阅:收集发布单独给一个中介

对比

  • 以结构来分辨模式,发布订阅模式相比观察者模式多了一个调度中心;

  • 以意图来分辨模式,都是实现了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,并自动更新,那么他们就是同一种模式;

  • 发布订阅模式是在观察者模式的基础上做的优化升级。观察者模式是发布订阅模式的一种特殊实现;

观察者和被观察者,是松耦合的关系
发布者和订阅者,则完全解耦

观察者模式,多用于单个应用内部
发布订阅模式,则更多的是一种跨应用的模式(cross-application pattern),比如我们常用的消息中间件

  • 在观察者模式中,观察者是知道Subject的,Subject一直保持对观察者进行记录。然而,在发布订阅模式中,发布者和订阅者不知道对方的存在。它们只能通过消息代理进行通信。

  • 观察者模式大多数时候是同步的,比如当事件触发,Subject就会去调用观察者的方法。而发布-订阅模式大多数时候是异步的(使用消息队列)

观察者模式

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

class Observer {constructor(name){this.name = name}update (price) {console.log(`${this.name},你好。我是房东A,我的房子刚刚降价到${price}万,赶紧来买!`)}
}
class Subject {constructor(price){this.price = pricethis.observerList = []}registerObserver(observer){this.observerList.push(observer)}notifyObserver(){this.observerList.forEach(observer=>observer.update(this.price))}setState (price){ //用来触发notifyObserverthis.price = priceif(price<=500){this.notifyObserver()}}
}
const A = new Subject(550)
const B = new Observer('B')
const C = new Observer('C')
const D = new Observer('D')
A.registerObserver(B)
A.registerObserver(C)setTimeout(function () {A.setState(510)// 1个月后,D也告诉房东500w一下他也想买// 只要D也有update方法,我们直接注册,并不用改变以后的逻辑代码// 实现了解耦,维护性好A.registerObserver(D)
},1000)
setTimeout(function () {A.setState(490)
},3000)

观察者模式由具体目标调度,每个被订阅的目标里面都需要有对观察者的处理,会造成代码的冗余。

    //有一家猎人工会,其中每个猎人都具有发布任务(publish),订阅任务(subscribe)的功能//他们都有一个订阅列表来记录谁订阅了自己//定义一个猎人类//包括姓名,级别,订阅列表function Hunter(name, level){this.name = namethis.level = levelthis.list = []}Hunter.prototype.publish = function (money){console.log(this.level + '猎人' + this.name + '寻求帮助')this.list.forEach(function(item, index){item(money)})}Hunter.prototype.subscribe = function (targrt, fn){console.log(this.level + '猎人' + this.name + '订阅了' + targrt.name)targrt.list.push(fn)}//猎人工会走来了几个猎人let hunterMing = new Hunter('小明', '黄金')let hunterJin = new Hunter('小金', '白银')let hunterZhang = new Hunter('小张', '黄金')let hunterPeter = new Hunter('Peter', '青铜')//Peter等级较低,可能需要帮助,所以小明,小金,小张都订阅了PeterhunterMing.subscribe(hunterPeter, function(money){console.log('小明表示:' + (money > 200 ? '' : '暂时很忙,不能') + '给予帮助')})hunterJin.subscribe(hunterPeter, function(){console.log('小金表示:给予帮助')})hunterZhang.subscribe(hunterPeter, function(){console.log('小金表示:给予帮助')})hunterPeter.publish(198)   //Peter遇到困难,赏金198寻求帮助//猎人们(观察者)关联他们感兴趣的猎人(目标对象),如Peter,当Peter有困难时,会自动通知给他们(观察者)

发布订阅模式

发布者只需告诉Broker,我要发的消息,topic是AAA;
订阅者只需告诉Broker,我要订阅topic是AAA的消息;

当Broker收到发布者发过来消息,并且topic是AAA时,就会把消息推送给订阅了topic是AAA的订阅者。当然也有可能是订阅者自己过来拉取,看具体实现。

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

class Event {constructor(){this.list = {}}on(name,fn){if(!this.list[name]){this.list[name] = []}this.list[name].push(fn)}emit(name,data) {this.list[name] && this.list[name].forEach(fn=>fn(data))}
}const event = new Event()
event.on('卖房',function (price) {if(price>=500){console.log(`现在房价${price}万。太高了,再等等吧`)}else{console.log(`现在房价${price}万。赶紧通知BCD买房`)}
})
event.emit('卖房',550)
setTimeout(()=>{event.emit('卖房',520)},1000)
setTimeout(()=>{event.emit('卖房',450)},2000)

发布订阅模式则统一由调度中心处理,消除了发布者和订阅者之间的依赖。

    //定义一家猎人工会//主要功能包括任务发布大厅(topics),以及订阅任务(subscribe),发布任务(publish)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)}}}//定义一个猎人类//包括姓名,级别function Hunter(name, level){this.name = namethis.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', '青铜')//小明,小金,小张分别订阅了狩猎tiger的任务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)//猎人们发布(发布者)或订阅(观察者/订阅者)任务都是通过猎

http://chatgpt.dhexx.cn/article/0AE1iGq4.shtml

相关文章

RabbitMQ:发布订阅模式

✨ RabbitMQ:发布订阅模式 1.订阅模式基本介绍2.交换机3.发布订阅模式3.1基本介绍3.2生产者3.3消费者3.4测试 &#x1f4c3;个人主页:不断前进的皮卡丘 &#x1f31e;博客描述:梦想也许遥不可及&#xff0c;但重要的是追梦的过程&#xff0c;用博客记录自己的成长&#xff0c;记…

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

JavaScript设计模式&#xff1a;四、发布订阅模式 文章目录 JavaScript设计模式&#xff1a;四、发布订阅模式一、概述1. 观察者模式2. 发布订阅模式3. 观察者模式是不是发布订阅模式 一、概述 观察者模式&#xff1a; 观察者&#xff08;Observer&#xff09;直接订阅&#x…

发布订阅模式理解

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

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

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

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 …