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

news2024/11/23 4:39:54

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

二 概念上的区别

1.观察者模式,目标和观察者是基类,目标提供维护观察者的一系列方法,观察者提供更新接口。具体观察者和具体目标继承各自的基类,然后具体观察者把自己注册到具体目标里,在具体目标发生变化时候,调度观察者的更新方法。

比如有个“天气中心”的具体目标A,专门监听天气变化,而有个显示天气的界面的观察者B,B就把自己注册到A里,当A触发天气变化,就调度B的更新方法,并带上自己的上下文。

2.发布订阅,订阅者把自己想订阅的事件注册到调度中心,当该事件触发时候,发布者发布该事件到调度中心(顺带上下文),由调度中心统一调度订阅者注册到调度中心的处理代码。

比如有个界面是实时显示天气,它就订阅天气事件(注册到调度中心,包括处理程序),当天气变化时(定时获取数据),就作为发布者发布天气信息到调度中心,调度中心就调度订阅者的天气处理程序。

三、发布订阅模式简介

定义和原理
发布订阅模式是一种消息传递模式,其中发布者发布消息,而订阅者接收和处理这些消息。它是一种松耦合的通信方式,允许发布者和订阅者在不知道彼此存在的情况下进行通信。

发布订阅模式的原理基于消息队列或主题,发布者将消息发布到特定的消息队列或主题中,而订阅者可以订阅这些消息队列或主题以接收和处理消息。发布者和订阅者之间的通信是异步的,这意味着发布者发布消息后,订阅者可以在任何时候接收和处理消息。

发布订阅模式的核心思想是将发布者和订阅者解耦,使得它们可以独立地运行和扩展。这种解耦有助于提高系统的灵活性和可伸缩性,因为发布者和订阅者可以根据需要进行扩展和修改,而不会影响彼此的操作。

发布订阅模式在许多领域都有应用,如

  • 消息队列
  • 事件驱动架构
  • 实时数据更新
  • 消息推送

它是一种非常有用的通信模式,可以帮助开发人员构建高效、可靠和可扩展的系统。

发布订阅模式的优势
发布订阅模式具有以下优势:
  1. 解耦:发布者和订阅者是松耦合的,它们可以独立地运行和扩展,而不会相互影响。
  2. 灵活性:发布者可以随时发布消息,而订阅者可以随时订阅和取消订阅消息,这使得系统更加灵活。
  3. 可伸缩性:发布者和订阅者可以根据需要进行扩展和修改,而不会影响彼此的操作。
  4. 异步通信:发布者和订阅者之间的通信是异步的,这意味着发布者发布消息后,订阅者可以在任何时候接收和处理消息。
  5. 消息过滤:订阅者可以根据自己的需求订阅特定的消息,从而实现消息过滤。
  6. 可靠性:发布订阅模式通常使用消息队列或主题来存储消息,这可以确保消息不会丢失,并且可以在订阅者不可用时进行存储。
  7. 分布式系统:发布订阅模式可以在分布式系统中使用,从而实现跨节点的通信。

 

四、发布订阅模式的实现

消息队列
发布订阅模式可以使用消息队列来实现。消息队列是一种存储和转发消息的技术,它可以在发布者和订阅者之间提供异步通信。

在发布订阅模式中,发布者将消息发布到消息队列中,而订阅者可以从消息队列中接收和处理消息。消息队列可以作为发布者和订阅者之间的中间件,它可以确保消息的可靠性和有序性。

使用消息队列实现发布订阅模式的步骤如下:

创建消息队列:创建一个消息队列来存储和转发消息。
发布消息:发布者将消息发布到消息队列中。
订阅消息:订阅者订阅消息队列以接收和处理消息。
处理消息:订阅者从消息队列中接收消息并进行处理。

在实现发布订阅模式时,需要考虑以下几个方面:

消息队列的选择:根据需求选择合适的消息队列,如 RabbitMQ、Kafka 等。
消息的格式:定义消息的格式,以便发布者和订阅者能够理解和处理消息。
消息的发布和订阅:确定发布者和订阅者如何发布和订阅消息。
消息的处理:订阅者需要根据自己的需求处理消息,如数据处理、日志记录等。
消息的可靠性:考虑如何确保消息的可靠性,如消息确认、消息重试等。
消息的有序性:考虑如何确保消息的有序性,如消息排序、消息分组等。

总之,使用消息队列实现发布订阅模式可以提供高效、可靠和可扩展的通信方式。在实现时,需要根据具体需求进行选择和配置。

发布订阅者
在发布订阅模式中,发布者和订阅者是两个独立的实体,它们通过某种通信渠道(如消息队列)进行交互。

发布者负责将消息发布到通信渠道中,而订阅者则负责从通信渠道中接收和处理消息。发布者和订阅者之间的通信是异步的,这意味着发布者发布消息后,订阅者可以在任何时候接收和处理消息。

以下是使用发布订阅模式实现发布者和订阅者的基本步骤:

  1. 创建通信渠道:创建一个消息队列或主题来存储和转发消息。
  2. 发布消息:发布者将消息发布到通信渠道中。
  3. 订阅消息:订阅者订阅通信渠道以接收和处理消息。
  4. 处理消息:订阅者从通信渠道中接收消息并进行处理。

在实现发布订阅模式时,需要考虑以下几个方面:

通信渠道的选择:根据需求选择合适的通信渠道,如消息队列、主题等。
消息的格式:定义消息的格式,以便发布者和订阅者能够理解和处理消息。
消息的发布和订阅:确定发布者和订阅者如何发布和订阅消息。
消息的处理:订阅者需要根据自己的需求处理消息,如数据处理、日志记录等。
消息的可靠性:考虑如何确保消息的可靠性,如消息确认、消息重试等。
消息的有序性:考虑如何确保消息的有序性,如消息排序、消息分组等。
总之,发布订阅模式实现发布者和订阅者之间的通信,提供了一种高效、可靠和可扩展的通信方式。在实现时,需要根据具体需求进行选择和配置。

消息主题
在发布订阅模式中,消息主题是用于发布和订阅消息的标识符。它是发布者和订阅者之间的桥梁,用于定义订阅者感兴趣的消息类型。

以下是使用消息主题实现发布订阅模式的基本步骤:

创建消息主题:创建一个唯一的消息主题来标识要发布的消息类型。
发布消息:发布者将消息发布到特定的消息主题中。
订阅消息:订阅者订阅特定的消息主题以接收和处理消息。
处理消息:订阅者从订阅的消息主题中接收消息并进行处理。

在实现发布订阅模式时,需要考虑以下几个方面:

消息主题的设计:设计合适的消息主题,以便发布者和订阅者能够理解和处理消息。
消息的发布和订阅:确定发布者和订阅者如何发布和订阅消息主题。
消息的处理:订阅者需要根据自己的需求处理消息,如数据处理、日志记录等。
消息的可靠性:考虑如何确保消息的可靠性,如消息确认、消息重试等。
消息的有序性:考虑如何确保消息的有序性,如消息排序、消息分组等。

总之,消息主题是发布订阅模式中的重要概念,用于定义发布者和订阅者之间的通信。在实现时,需要根据具体需求进行选择和配置。

五、发布订阅模式的
应用场景
实时数据更新
消息推送
事件驱动架构
注意事项
消息丢失和重复
消息顺序问题
消息过期问题

 

六 总结

1. 最大的区别是调度的地方。

虽然两种模式都存在订阅者和发布者(具体观察者可认为是订阅者、具体目标可认为是发布者),但是观察者模式是由具体目标调度的,而发布/订阅模式是统一由调度中心调的,所以观察者模式的订阅者与发布者之间是存在依赖的,而发布/订阅模式则不会。2. 两种模式都可以用于松散耦合,改进代码管理和潜在的复用。

七, 代码如下

观察者模式

// 观察者
class Observer {
    constructor() {
 
    }
    update(val) {
 
    }
}
// 观察者列表
class ObserverList {
    constructor() {
        this.observerList = []
    }
    add(observer) {
        return this.observerList.push(observer);
    }
    remove(observer) {
        this.observerList = this.observerList.filter(ob => ob !== observer);
    }
    count() {
        return this.observerList.length;
    }
    get(index) {
        return this.observerList(index);
    }
}
// 目标
class Subject {
    constructor() {
        this.observers = new ObserverList();
    }
    addObserver(observer) {
        this.observers.add(observer);
    }
    removeObserver(observer) {
        this.observers.remove(observer);
    }
    notify(...args) {
        let obCount = this.observers.count();
        for (let index = 0; index < obCount; index++) {
            this.observers.get(i).update(...args);
        }
    }
}

 发布/订阅模式

class PubSub {
    constructor() {
        this.subscribers = {}
    }
    subscribe(type, fn) {
        if (!Object.prototype.hasOwnProperty.call(this.subscribers, type)) {
          this.subscribers[type] = [];
        }
        
        this.subscribers[type].push(fn);
    }
    unsubscribe(type, fn) {
        let listeners = this.subscribers[type];
        if (!listeners || !listeners.length) return;
        this.subscribers[type] = listeners.filter(v => v !== fn);
    }
    publish(type, ...args) {
        let listeners = this.subscribers[type];
        if (!listeners || !listeners.length) return;
        listeners.forEach(fn => fn(...args));        
    }
}
 
let ob = new PubSub();
ob.subscribe('add', (val) => console.log(val));
ob.publish('add', 1);

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

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

相关文章

【Vue3】搭建Pinia环境及其基本使用

下载 npm i pinia引入并注册 App.vue import { createApp } from vue import { createPinia } from pinia import App from ./App.vue // 1. 引入 import { createPinia } from piniaconst app createApp(App) // 2. 创建 const pinia createPinia() // 3. 注册 app.use(p…

python----面向对象

这里写目录标题 面向对象思想类类的定义类名的定义类的构造函数的定义类的属性类的方法定义 继承语法关于构造函数问题 文件操作绝对路径相对路径pycharm获取绝对路径和相对路径文件读写读文件open&#xff08;&#xff09;read&#xff08;&#xff09;readline&#xff08;&a…

2021年CSP-J认证 CCF信息学奥赛中小学初级组 第一轮真题-单项选择题解析

2021年 中小学信息学奥赛CSP-J真题解析 1、以下不属于面向对象程序设计语言的是 A、c B、python C、java D、c 答案&#xff1a;D 考点分析&#xff1a;主要考查编程语言&#xff0c;ABC都是面向对象语言&#xff0c;D选项c语言是面向过程语言&#xff0c;答案D 2、以下奖…

202427读书笔记|《猫的自信:治愈系生活哲学绘本》——吸猫指南书,感受猫咪的柔软慵懒与治愈

202427读书笔记|《猫的自信&#xff1a;治愈系生活哲学绘本》——吸猫指南书&#xff0c;感受猫咪的柔软慵懒与治愈 《猫的自信&#xff1a;治愈系生活哲学绘本》作者林行瑞&#xff0c;治愈系小漫画绘本&#xff0c;10分钟可以读完的一本书&#xff0c;线条明媚&#xff0c;自…

SQL注入工具之SQLmap入门操作

了解SQLmap 基础操作 SQLmap是一款自动化的SQL注入工具&#xff0c;可以用于检测和利用SQL注入漏洞。 以下是SQLmap的入门操作步骤&#xff1a; 1.下载SQLmap&#xff1a;可以从官方网站&#xff08;https://sqlmap.org/&#xff09;下载最新版本的SQLmap。 2.打开终端&#…

CDP和Chrome

CDP和Chrome CDP和WebDriver Protocol WebDriver和 Chrome DevTools Protocol&#xff08;CDP&#xff09; 是用于自动化浏览器的两个主要协议&#xff0c;大多数的浏览器自动化工具都是基于上述其中之一来实现的。可以通过这两种形式来和浏览器交互&#xff0c;通过代码来控…

使用maven集成spring在测试的时候报出了如下的异常:version 60

使用maven集成spring在测试的时候报出了如下的异常&#xff1a; Caused by: java.lang.IllegalArgumentException: Unsupported class file major version 60 解决&#xff1a;

MAC M1安装vmware和centos7虚拟机并配置静态ip

一、下载vmware和centos7镜像 1、VMWare Fusion 官网的下载地址是&#xff1a;下载地址 下载好之后注册需要秘钥&#xff0c;在官网注册后使用免费的个人秘钥 2、centos7 下载地址&#xff1a; https://biosyxh.cn:5001/sharing/pAlcCGNJf 二、虚拟机安装 直接将下…

比特币正在蚕食黄金

号外&#xff1a;教链内参2.19《内参&#xff1a;蹭热点、骗流量、割韭菜》 众所周知&#xff0c;自从美国SEC批准比特币现货ETF登陆美股市场之后&#xff0c;打开了美国金融市场泛滥的流动性向比特币流入的大门。只用了短短的30个交易日&#xff0c;比特币ETF就从零膨胀到了近…

基于RBAC的权限管理的理论实现和权限管理的实现

权限管理的理论 首先需要两个页面支持&#xff0c;分别是角色管理和员工管理&#xff0c;其中角色管理对应的是角色和权限的配合&#xff0c;员工管理则是将登录的员工账号和员工所处的角色进行对应&#xff0c;即通过新增角色这个概念&#xff0c;让权限和员工并不直接关联&a…

Ubuntu18.04有线连接后,无法设置ip地址以及显示网口设置

前提&#xff1a;首先测试过网线是完全没问题的 桌面端找不到设置网口 终端输入&#xff1a; ifconfig 没有找到网口设置和对应IP 然后查询网口驱动是否正常安装&#xff0c;输入&#xff1a; lspci | grep Ethernet 有输出说明网口驱动正常安装 然后查询电脑的ip地址&am…

2023年全球软件开发大会(QCon北京站2023)2月:核心内容与学习收获(附大会核心PPT下载)

本次峰会是一个汇集了最新技术趋势、最佳实践和创新思维的盛会。对于从事软件开发和相关领域的专业人士来说&#xff0c;参加这样的大会将有助于他们了解行业动态、提升技能水平、拓展职业视野&#xff0c;并与同行建立联系和合作。 本次峰会包含&#xff1a;AI基础架构、DevO…

Stable Diffusion 绘画入门教程(webui)-lora

通过前边的文章&#xff0c;相信大家已经能够自己产出好看的小姐姐或者小哥哥了&#x1f923; 不知道有没有发现每次生成的脸、身材、衣服、环境、风格等等可能都会有所差异&#xff0c;那么如果这个问题不解决&#xff0c;实用性将大大降低&#xff0c;因此lora诞生了。 文章…

人工智能_普通服务器CPU_安装清华开源人工智能AI大模型ChatGlm-6B_001---人工智能工作笔记0096

使用centos安装,注意安装之前,保证系统可以联网,然后执行yum update 先去更新一下系统,可以省掉很多麻烦 20240219_150031 这里我们使用centos系统吧,使用习惯了. ChatGlm首先需要一台个人计算机,或者服务器, 要的算力,训练最多,微调次之,推理需要算力最少 其实很多都支持C…

SpringBoot常见问题

1 引言 Spring Boot是一个基于Spring框架的快速开发脚手架&#xff0c;它简化了Spring应用的初始化和搭建过程&#xff0c;提供了众多便利的功能和特性&#xff0c;比如自动配置、嵌入式Tomcat等&#xff0c;让开发人员可以更加专注于业务逻辑的实现。   Spring Boot还提供了…

IO进程线程作业day2

使用fread和fwrite完成两个图片文件的拷贝 #include <myhead.h> #define high 541 #define wide 541 int main(int argc, const char *argv[]) {//以只读的方式打开图片文件1.bmpFILE *fp NULL;if((fp fopen("./1.bmp", "r")) NULL){perror(&qu…

数据分析 - 机器学习

1&#xff1a;线性回归 线性回归是一种统计技术用于对输出变量与一个或多个输入变量之间的关系进行建模 用外行人的话来说&#xff0c;将其视为通过某些数据点拟合一条线&#xff0c;如下所示 以便在未知数据上进行预测&#xff0c;假设变量之间存在线性关系 点和线之间存在微小…

实体类赋值之后,数据库属性最后为null的解决方法

目录 1. 问题所示2. 原理分析1. 问题所示 执行代码赋值的时候,通过Debug可以看到成功被赋值,但执行到最后,该数据库的属性为null 如图所示: 2. 原理分析 针对这种情况,排查了一个晚上才找到根本原因 最后发现是持久化操作的问题,本身赋值之后,对于数据库还要执行一个…

112. Path Sum(路径总和)

问题描述 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 叶子节点 是指…

MCAL知识点(二十七):TC275如何通过GPT12实现ABZ解码

目录 1、概述 2、代码实现 1、概述 GPT12 - General Purpose Timer Unit (GPT12):通用定时器单元,具备较为灵活的定时器结构,可以用来做定时器、事件计数、脉冲宽度测量、产生PWM、频率调制、ABZ编码器增量测量。文章记录一下如何通过GPT12实现编码器ABZ信号的测量。 注意…