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

news2024/11/11 5:12:05

目录

模式简介

介绍

优点

缺点

代码实现

场景说明

实现代码

运行结果


模式简介

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

介绍

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

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

优点

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

缺点

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

代码实现

场景说明

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

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

实现代码

/*

observer1 observer2 observer3

		Subject (主题)主题更改,应该及时通知相应的观察者,去处理相应的事件
*/
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);//发起通知
	}
}

运行结果如下

 

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

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

相关文章

4-3 Working with time series

本文所用数据下载 Data from a Washington, D.C., bike-sharing system reporting the hourly count of rental bikes in 2011–2012 in the Capital Bikeshare system, along with weather and seasonal information. Our goal will be to take a flat, 2D dataset and trans…

搭建网站 --- 快速WordPress个人博客并内网穿透发布到互联网

文章目录 快速WordPress个人博客并内网穿透发布到互联网 快速WordPress个人博客并内网穿透发布到互联网 我们能够通过cpolar完整的搭建起一个属于自己的网站&#xff0c;并且通过cpolar建立的数据隧道&#xff0c;从而让我们存放在本地电脑上的网站&#xff0c;能够为公众互联…

JS——输入输出语法数组的操作

JavaScript输入输出语法 目标&#xff1a;能写出常见的JavaScript输入输出语法 输出语法 语法1&#xff1a; document.write(要输出的内容)作用&#xff1a; 向body内输出内容 注意&#xff1a; 如果输出的内容写的是标签&#xff0c;也会被解析成网页元素 语法2&#xff1a…

2023大同首届信息技术产业峰会举行,共话数字经济新未来

7月28日&#xff0c;“聚势而强共领信创”2023大同首届信息技术产业峰会圆满举行。本次峰会由中共大同市委、大同市人民政府主办&#xff0c;中国高科技产业化研究会国际交流合作中心、山西省信创协会协办&#xff0c;中共大同市云冈区委、大同市云冈区人民政府、诚迈科技&…

一文深入了解Cmk

目录 一、Cmk&#xff08;设备能力指数&#xff09;介绍&#xff1a;二、Cmk&#xff08;设备能力指数&#xff09; 概念&#xff1a;三、Cmk的应用时机&#xff1a;四、Cmk前期准备和要求&#xff1a;五、Cmk测试要求&#xff1a;六、CMK计算公式&#xff1a;七、Cmk实际操作&…

机器学习的关键词和算法总结

随着全球各行业的数据治理、数字化转型智能化辅助的引入发展&#xff0c;机器学习&#xff08;包括深度学习&#xff09;在逐步深入到各行各业&#xff0c;所以&#xff0c;有必要对机器学习的常见术语&#xff0c;经典算法及应用场景进行一次总结&#xff0c;其实机器学习兴起…

Vue2 第九节 过滤器

&#xff08;1&#xff09;定义&#xff1a;对要显示的数据进行特定格式化后再显示 &#xff08;2&#xff09;语法&#xff1a; ① 注册过滤器 1&#xff09;Vue.filter(name, callback) 全局过滤器 2&#xff09; new Vue({filters:{}}) 局部过滤器 ② 使用过滤器 1&…

SQL注入漏洞及解决(PreparedStatement对象)

四、SQL注入漏洞 加个or true都能查出来&#xff0c;很危险&#xff01;&#xff01;&#xff01; 会报错&#xff0c;因为代码中也拼了个引号 我们使用#将后面的内容注释起来&#xff0c;前面还是条完整的sql&#xff0c;还是能查到 使用—注释&#xff0c;代码可能加trim()&…

编译运行miniob最小数据库系统

minibo是一个用于教学的小型数据库系统&#xff0c;麻雀虽小五脏俱全&#xff0c;该项目包含了数据库的核心内容&#xff0c;并且代码量小&#xff0c;适合新手学习&#xff0c;最近由于需要学习c/cpp&#xff0c;因此打算从这个项目入手&#xff0c;本文就介绍编译运行miniob的…

《零基础入门学习Python》第072讲:GUI的终极选择:Tkinter9

这节课我们接着来讲解 Canvas 组件&#xff0c;既然 Cnavas 是画布的意思&#xff0c;那我们能不能让这个组件来设计一个画板呢&#xff1f;像Windows 自带的画图程序&#xff0c;我们的用户可以在上面随心所欲的绘制自己想要的图画&#xff0c;大家仔细想想&#xff0c;其实画…

美团小图币代挂教程

登陆美团官网获取对应的cookie 美团官网&#xff0c;点击右上角登陆对应账号。登陆成功后使用f12来获取 cookie 此时如果没有任何数据&#xff0c;点击网页刷新。找到如下的网络请求 赋值cookie项的全部内容&#xff0c;此时已经获取到对应账号的cookie 使用cookie登陆代挂…

NODEJS笔记

全局对象 global/window console.log/info/warn/error/time/timeEnd process.arch/platform/version/env/kill/pid/nextTick Buffer.alloc(5,abcde) String/toString setTimeout/clearTimeout setInterval/clearInterval setImmediate/clearImmediate process.nextTi…

1.netty介绍

1.介绍 是JBOSS通过的java开源框架是异步的,基于事件驱动(点击一个按钮调用某个函数)的网络应用框架,高性能高可靠的网络IO程序基于TCP,面向客户端高并发应用/点对点大量数据持续传输的应用是NIO框架 (IO的一层层封装) TCP/IP->javaIO和网络编程–>NIO—>Netty 2.应用…

HTTP请求走私漏洞简单分析

文章目录 HTTP请求走私漏洞的产生HTTP请求走私漏洞的分类HTTP请求走私攻击的危害确认HTTP请求走私漏洞通过时间延迟技术确认CL漏洞通过时间延迟技术寻找TE.CL漏洞 使用差异响应内容确认漏洞通过差异响应确认CL.TE漏洞通过差异响应确认TE.CL漏洞 请求走私漏洞的利用通过请求漏洞…

【面试题】与通义千问的芯片前端设计模拟面试归纳

这里是尼德兰的喵芯片设计相关文章,欢迎您的访问! 如果文章对您有所帮助,期待您的点赞收藏! 让我们一起为芯片前端全栈工程师而努力! 前言 两个小时,与chatGPT进行了一场数字IC前端设计岗的面试_尼德兰的喵的博客-CSDN博客 和GPT-3.5的回答可以对比品尝,味道更好。 模…

nacos源码打包及相关配置

nacos 本地下载后&#xff0c;需要 install 下&#xff1a; mvn clean install -Dmaven.test.skiptrue -Dcheckstyle.skiptrue -Dpmd.skiptrue -Drat.skiptruenacos源码修改后&#xff0c;重新打包生成压缩包命令&#xff1a;在 distribution 目录中运行&#xff1a; mvn -Pr…

数字化转型导师坚鹏:数字化时代扩大内需的8大具体建议

在日新月异的数字化时代、复杂多变的国际化环境下&#xff0c;扩大内需成为推动经济发展的国家战略&#xff0c;如何真正地扩大内需&#xff1f;结合本人15年的管理咨询经验及目前实际情况的深入研究&#xff0c;提出以下8大具体建议&#xff1a; 1、制定国民收入倍增计划。结…

QObject::connect: No such signal me::sendMsg(QString s) in ...

QObject::connect: No such signal me::sendMsg&#xff08;QString s&#xff09; in ... 解决方案 在使用qt4的connect中&#xff0c;爆的bug&#xff1a; 导致 teacher 的槽函数 receiveMsg(QString s) 一直没有被调用。。。。 解决方案 去掉参数名&#xff0c; 保留类型…

spring6——容器

文章目录 容器&#xff1a;IocIoc容器控制反转&#xff08;Ioc&#xff09;依赖注入IoC容器在Spring的实现 基于XML管理Bean搭建环境获取bean依赖注入setter注入构造器注入特殊值处理字面量赋值null值xml实体CDATA节 特殊类型属性注入为对象类型属性赋值方式一&#xff1a;引入…

Spring依赖注入和ioc在spring中的实现方式

目录 一、依赖注入 1.IOC思想 2.什么是依赖注入&#xff1f; 3.实例化对象中有pojo类型属性 二、IOC在Spring中的实现方式 1.获取bean的三种方式 1.1根据bean的id获取 1.2根据bean的类型获取&#xff08;最常用&#xff0c;因为在IOC容器中&#xff0c;一个类型的bean只…