当前位置: 首页 > news >正文

C++之观察者模式(发布-订阅)

目录

模式简介

介绍

优点

缺点

代码实现

场景说明

实现代码

运行结果


模式简介

观察者模式(Observer Pattern,也叫我们熟知的发布-订阅模式。
它是一种行为型模式。

介绍

观察者模式主要关注的是对象的一对多的关系,
也就是多个对象依赖于一个对象,当该对象的状态发生改变时,其他对象都能够收到相应的通知

意图:
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
主要解决:
一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
如何解决:
使用面向对象技术,可以将这种关系弱化。

优点

  1. 观察者和被观察者是抽象耦合的;
  2. 建立了一套触发机制。

缺点

  1. 如果一个被观察者对象有很多的直接和间接的观察者的话,通知所有的观察者需要花费很长的时间
  2. 如果在观察者和被观察者目标之间有循环依赖的话,观察目标会触发他们之间的循环调用,可能会导致系统崩溃;
  3. 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅是知道观察目标发生了变化。

代码实现

场景说明

我们现在有三个观察者三种消息,这三个观察者分别对不同的消息感兴趣

我们实现的话,可以简单的设置三个观察者,一个主题类(被观察者)。
这三个观察者可以设置自己喜欢的、感兴趣的消息类型(1、2、3)。
他们处理收到的消息就是打印一下自己收到了什么消息。
具体实现如下

实现代码

/*observer1 observer2 observer3Subject (主题)主题更改,应该及时通知相应的观察者,去处理相应的事件
*/
class Observer // 观察者抽象类
{
public://处理消息的接口virtual void handle(int msgid) = 0;
};//第一个观察者实例
class Observer1 : public Observer
{
public:void handle(int msgid){switch (msgid){case 1:cout << "Observer1 recv 1 msg" << endl;break;case 2:cout << "Observer1 recv 2 msg" << endl;break;default:cout << "Observer1 recv unkonw msg!" << endl;break;}}
};
//第二个观察者实例
class Observer2 : public Observer
{
public:void handle(int msgid){switch (msgid){case 2:cout << "Observer2 recv 2 msg" << endl;break;default:cout << "Observer2 recv unkonw msg!" << endl;break;}}
};
//第三个观察者实例
class Observer3 : public Observer
{
public:void handle(int msgid){switch (msgid){case 1:cout << "Observer3 recv 1 msg" << endl;break;case 3:cout << "Observer3 recv 3 msg" << endl;break;default:cout << "Observer3 recv unkonw msg!" << endl;break;}}
};//主题类
class Subject
{
public://给主题增加观察者对象void addObserver(Observer* obser,int msgid){_subMap[msgid].push_back(obser);}//主题检测发生改变,通知相应的观察者对象处理事件void dispatch(int msgid){auto it = _subMap.find(msgid);if (it != _subMap.end()){//通过多态,实现不同的指向for (Observer* pObser : it->second){pObser->handle(msgid);}}}
private://用来保存订阅的消息unordered_map<int, list<Observer*>> _subMap;
};

我们可以看到主题类(Subject)的数据成员是一个unordered_map。使用这个是因为我们不需要数据是有序的,为了提高增删查的速率,使用了无序map。
使用map的好处是,它作为一个键值对,可以存储我们想要的数据类型:(消息类型,订阅此消息类型的观察者们)。

并且,在主题类(Subject)的成员方法addObserver中,我们使用了一个中括号运算符([])重载的特性:
如果当前容器中存有相应的msgid键的话,就直接添加对应的值(Obser);
如果当前容器中没有相应的msgid键的话,就直接添加该键,并且添加一个默认的值。

运行结果

我们使用如下的代码:

void main()
{Subject subject;Observer* p1 = new Observer1();Observer* p2 = new Observer2();Observer* p3 = new Observer3();subject.addObserver(p1, 1);subject.addObserver(p1, 2);subject.addObserver(p2, 2);subject.addObserver(p3, 1);subject.addObserver(p3, 3);int msgid = 0;for (;;){cout << "请输入消息id:" << endl;cin >> msgid;if (msgid == -1)break;subject.dispatch(msgid);//发起通知}
}

运行结果如下

 

相关文章:

C++之观察者模式(发布-订阅)

目录 模式简介 介绍 优点 缺点 代码实现 场景说明 实现代码 运行结果 模式简介 观察者模式&#xff08;Observer Pattern&#xff09;&#xff0c;也叫我们熟知的发布-订阅模式。 它是一种行为型模式。 介绍 观察者模式主要关注的是对象的一对多的关系&#xff0c; …...

无头单链表,有完整测试程序

&#x1f35f;无头单链表 &#x1f47b;无头单链表的所有结点都存储有效信息 &#x1f47b;无头单链表相对带头单链表&#xff0c;在有些涉及更改头节点的函数上需要传二级指针 &#x1f35f;头文件list.h #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #includ…...

2023年第四届“华数杯”数学建模思路 - 案例:FPTree-频繁模式树算法

## 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法&#xff0c;就是频繁模式树算法&#xff0c;他与Apriori算法一样也是用来挖掘频繁项集的&#xff0c…...

MySQL做分布式锁

分布式锁mysql实现方式 方式1&#xff1a;唯一索引 创建锁表&#xff0c;内部存在字段表示资源名及资源描述&#xff0c;同一资源名使用数据库唯一性限制。多个进程同时往数据库锁表中写入对某个资源的占有记录&#xff0c;当某个进程成功写入时则表示其获取锁成功其他进程由于…...

Python学习笔记:变量类型、字符串基本操作

1.注释 单行注释 # 单行注释 多行注释 """ 多行注释 """2.变量类型 # 基本变量类型 a 1 # integer b 1.5 # float c string # String d "string" # string e False # boolean # list\tuple\dictionar…...

JVM的组件、自动垃圾回收的工作原理、分代垃圾回收过程、可用的垃圾回收器类型

详细画的jvm模型图 https://www.processon.com/diagraming/64c8aa11c07d99075d934311 官方网址 https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html 相关概念 年轻代是所有新对象被分配和老化的地方。当年轻代填满时&#xff0c;这会导致m…...

【elementui】解决el-select组件失去焦点blur事件每次获取的是上一次选中值的问题

目录 【问题描述】 【问题摘要】 【分析问题】 【完整Test代码】 【封装自定义指令】 ↑↑↑↑↑↑↑↑↑↑↑↑ 不想看解决问题过程的可点击上方【封装自定义指令】目录直接跳转获取结果即可~~~ 【问题描述】 一位朋友遇到这么一个开发场景&#xff1a;在表格里面嵌入el-…...

通过了PMP考试,还有什么证书值得考?

自从7月24号公布了PMP成绩后&#xff0c;不少伙伴私信小编&#xff1a;通过PMP后还有哪些证书可以提升自己&#xff1f;一来是多份高含金量的证书可以多点竞争力&#xff0c;二来是加持自己的职业发展&#xff01;今天小编就来给大家捋一捋&#xff01; 一.NPDP认证 2016 年 4…...

页面技术基础-html

页面技术基础-html 环境准备&#xff1a;在JDBC中项目上完成代码定义 1. 新建一个 Module:filr->右键 -》Module -》Java-》next->名字(html_day1)->finish 2. 在 Moudle上右键-》第二个选项&#xff1a;add framework .. -> 选择JavaEE下第一个选项 Web Apllicat…...

/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28‘ not found

某项目中&#xff0c;我要给别人封装一个深度学习算法的SDK接口&#xff0c;运行在RK3588平台上&#xff0c;然后客户给我的交叉编译工具链是 然后我用他们给我的交叉编译工具链报下面的错误&#xff1a; aarch64-buildroot-linux-gnu-gcc --version /data/chw/aarch64/bin/cca…...

解决SVN或GIT忽略提交文件的问题

背景 使用IDEA 的SVN插件提交文件是总是会提交一些不需要提交的文件; 我们可以通过一些简单设置忽略这些文件。 git 在项目根目录新建文本文件&#xff0c;修改后缀为.gitignore 文件中添加内容 *.iml .project .gradle/ .idea/ target/ build/ .vscode/ .settings/ .facto…...

Django框架之路由用法

简介 路由简单的来说就是根据用户请求的 URL 链接来判断对应的处理程序&#xff0c;并返回处理结果&#xff0c;也就是 URL 与 Django 的视图建立映射关系。 Django 路由在 urls.py 配置&#xff0c;urls.py 中的每一条配置对应相应的处理方法。 Django 不同版本 urls.py 配…...

回文链表 LeetCode热题100

题目 给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为回文链表。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 思路 利用快慢指针找到链表中间节点&#xff0c;反转后半段链表。前半段从头节点开始与后半段比较。 注意当链表节点…...

如何在群晖NAS中使用cpolar内网穿透

如何在群晖nas中使用cpolar内网穿透 文章目录 如何在群晖nas中使用cpolar内网穿透 今天&#xff0c;我们来为大家介绍&#xff0c;如何在群晖系统中&#xff0c;使用图形化界面的cpolar。 cpolar经过图形化改造后&#xff0c;使用方法已经简便了很多&#xff0c;基本与其他应用…...

无头单向不循环链表和带头双向循环链表的创建

Lei宝啊&#xff1a;个人主页 愿所有美好不期而遇 前言&#xff1a; 接下来我们将会了解最基础的链表--->单链表 以及最方便也是最爽的链表--->带头双向循环链表。 若有看不懂之处&#xff0c;可画图或者借鉴这里&#xff1a;反转单链表&#xff0c;对于数据结构而言&am…...

超简单的fastapi链接websocket用例

main.py from typing import Listfrom fastapi import FastAPI, WebSocket, WebSocketDisconnectapp FastAPI()class ConnectionManager:def __init__(self):# 存放激活的ws连接对象self.active_connections: List[WebSocket] []async def connect(self, ws: WebSocket):# 等…...

MySQL详解

目录 一、MySQL 概述二、MySQL 安装和配置三、MySQL 基础语法四、MySQL 高级语法五、MySQL 性能优化六、MySQL 应用场景和实例七、MySQL 开发工具和插件八、MySQL 学习资源和社区 一、MySQL 概述 MySQL 是一种开源的关系型数据库管理系统&#xff0c;最初由瑞典的 MySQL AB 公…...

Vue [Day2]

指令修饰符 v-model.trim v-model.number 事件名.stop click.stop 事件名.prevent keyup.enter <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-w…...

【前端|Javascript第1篇】一文搞懂Javascript的基本语法

欢迎来到JavaScript的奇妙世界&#xff01;作为前端开发的基石&#xff0c;JavaScript为网页增色不少&#xff0c;赋予了静态页面活力与交互性。如果你是一名前端小白&#xff0c;对编程一无所知&#xff0c;或者只是听说过JavaScript却从未涉足过&#xff0c;那么你来对了地方…...

【Linux命令200例】cp用于复制文件和目录(常用)

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;本文已收录于专栏&#xff1a;Linux命令大全。 &#x1f3c6;本专栏我们会通过具体的系统的命令讲解加上鲜…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

【Linux】Linux 系统默认的目录及作用说明

博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1&#xff09;准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2&#xff09;服务端安装软件&#xff1a;bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...

iview框架主题色的应用

1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题&#xff0c;无需引入&#xff0c;直接可…...

群晖NAS如何在虚拟机创建飞牛NAS

套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...

嵌入式常见 CPU 架构

架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集&#xff0c;单周期执行&#xff1b;低功耗、CIP 独立外设&#xff1b;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel&#xff08;原始…...