【C++基础】观察者模式(“发布-订阅”模式)

news2024/11/19 21:23:38

  本文参考:观察者模式 - 摩根斯 | 爱编程的大丙

观察者模式允许我们定义一种订阅机制,可在对象事件发生时通知所有的观察者对象,使它们能够自动更新。观察者模式还有另外一个名字叫做“发布-订阅”模式。

发布者:

添加订阅者,将所有的订阅者存储起来
删除订阅者,将其从订阅者列表中删除
将消息发送给订阅者(发通知)

下面举一个生动的例子:

NewsAgency是一个抽象类,表示发布者,其派生类为 Morgans和Gossip,代表不同的两个报社

NewAgency.h

#pragma once
#include <string>
#include <list>

using namespace std;

//声明订阅者类
class Observer;

class NewsAgency
{
public:
	void attach(Observer* ob);  //添加订阅者
	void deatch(Observer* ob);  //删除订阅者
	virtual void notify(string msg) = 0;  //通知list中的所有订阅者
	virtual ~NewsAgency() {};   //析构

protected:
	list<Observer*> m_list;   //存储订阅者对象
};


class Morgans :public NewsAgency
{
public:
	void notify(string msg) override;
};

class Gossip :public NewsAgency
{
public:
	void notify(string msg) override;
};

 在NewsAgency.cpp,重写子类的虚函数。

#include "NewsAgency.h"
#include "Observer.h"
#include <iostream>


void NewsAgency::attach(Observer* ob)
{
	m_list.push_back(ob);
}

void NewsAgency::deatch(Observer* ob)
{
	m_list.remove(ob);
}


void Morgans::notify(string msg)
{
	cout << "摩根斯新闻社报纸的订阅者一共有" << m_list.size()  << endl;
	for (const auto& item : m_list)
	{
		item->update(msg);	// 订阅者类的定义在下面
	}
}


void Gossip::notify(string msg)
{
	cout << "八卦新闻社报纸的订阅者一共有 " << m_list.size() << endl;
	for (const auto& item : m_list)
	{
		item->update(msg);
	}


}

订阅者(也可称为观察者):

 Observer.h

首先给所有的观察者定义一个抽象的基类。

然后子类在各自的类中分别重写了update()这个状态更新函数

#pragma once
#include <string>
#include <iostream>
#include "NewsAgency.h"

//抽象的订阅者类
class Observer
{
public:
	//需要通过构造函数给观察者类提供一个信息的发布者
	//通过发布者对象将观察者对象存储了起来,这样就可以收到发布者推送的消息了。
	Observer(string name, NewsAgency* news)
		:m_name(name), m_news(news)
	{
		m_news->attach(this);
	}
	//观察者取消订阅,取消之后将不再接收订阅消息。
	void unsubscribe()
	{
		m_news->deatch(this);
	}
	//观察者得到最新消息之后,用于更新自己当前的状态。
	virtual void update(string msg) = 0;
	virtual ~Observer() {};

protected:
	string m_name;
	NewsAgency* m_news;
};


class Dragon :public Observer
{
public:
	using Observer::Observer;
	void update(string msg) override
	{
		cout<< "路飞的老爸革命军龙收到消息: " << msg << endl;
	}
};


class Shanks : public Observer
{
public:
	using Observer::Observer;
	void update(string msg) override
	{
		cout << "路飞的引路人红发香克斯收到消息: " << msg << endl;
	}
};

class Bartolomeo : public Observer
{
public:
	using Observer::Observer;
	void update(string msg) override
	{
		cout << "路飞的头号粉丝巴托洛米奥收到消息: " << msg << endl;
	}
};




main函数:

#include <iostream>
#include "NewsAgency.h"
#include "Observer.h"

using namespace std;


int main()
{
	Morgans* ms = new Morgans;
	Gossip* gossip = new Gossip;
	Dragon* dragon = new Dragon("蒙奇·D·龙", ms);
	Shanks* shanks = new Shanks("香克斯", ms);
	Bartolomeo* barto = new Bartolomeo("巴托洛米奥", gossip);

	ms->notify("蒙奇·D·路飞成为新世界的新的四皇之一, 赏金30亿贝里!!!");

	cout << "======================================" << endl;
	gossip->notify("女帝汉库克想要嫁给路飞, 给路飞生猴子, 哈哈哈...");

	delete ms;
	delete gossip;
	delete dragon;
	delete shanks;
	delete barto;
   
}

最后总结一下观察者模式的应用场景:
当一个对象的状态发生变化,并且需要改变其它对象的时候;或者当应用中一些对象必须观察其它对象的时候可以使用观察者模式。

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

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

相关文章

【数据关联(1)】Tracking-by-detection 多目标跟踪范式与“数据关联”的关系说明

这个领域有一些专有名词需要大家清楚&#xff01; 文章目录 1 Tracking-by-detection multi-object tracking(MOT) 范式跟踪器是什么&#xff1f;1.1 关系图&#xff08;个人理解&#xff0c;如有错误请指正&#xff09;1.2 跟踪器有哪些&#xff1f; 2、核心部分“数据关联”…

Python格式化字符串(格式化输出)

print() 函数的用法&#xff0c;这只是最简单最初级的形式&#xff0c;print() 还有很多高级的玩法&#xff0c;比如格式化输出&#xff0c;这就是本节要讲解的内容。 熟悉C语言 printf() 函数的读者能够轻而易举学会 Python print() 函数&#xff0c;它们是非常类似的。 pri…

SegNetr: 重新思考 U 形网络中的局部-全局交互和跳过连接

SegNetr 会议分析摘要贡献方法整体框架1. SegNetr Block2.Information Retention Skip Connection 实验1.对比实验2.消融实验2.1 Effect of local-global interactions.2.2 Effect of patch size2.3 Effect of IRSC 可借鉴参考 会议分析 论文出处&#xff1a; arXiv预印版 除了…

C++在C语言基础上的优化

目录 一、命名空间 1、命名空间的定义 2、命名空间的使用 二、输入&输出 三、缺省参数 1、缺省参数的概念 2、缺省参数的分类 四、函数重载 五、引用 1.引用的概念 2.引用的特性 3、引用和指针的区别 六、内联函数 七、基于范围的for循环 一、命名空间 命名空…

计算机网络第六章——应用层(下)

等闲变却故人心&#xff0c;却道故人心易变 文章目录 用户代理就是用户和电子邮件系统之间的一个接口&#xff0c;通常都是运行在电脑中的一个程序&#xff0c;用户代理又可以称为电子邮件客户端软件&#xff0c;用户代理可以为用户提供一个比较友好的接口&#xff0c;邮件服务…

详解初阶数据结构之顺序表(SeqList)——单文件实现SeqList的增删查改

目录 一、线性表 二、顺序表 2.1概念及结构 2.2接口实现 2.3动态顺序表的创建 2.3动态顺序表的初始化 2.3.1传值初始化 2.3.2传址初始化 2.4动态顺序表的清空 2.5动态顺序表的扩容 2.6动态顺序表内容的打印 三、动态顺序表的使用 3.1尾插尾删 3.1.1尾插 3.1.2尾删…

集合框架和泛型二

一、Set接口 1. Set接口概述 java.util.Set 不包含重复元素的集合、不能保证存储的顺序、只允许有一个 null。 public interface Set<E> extends Collection<E>抽象方法&#xff0c;都是继承自 java.util.Collection 接口。 Set 集合的实现类有很多&#xff0c;…

分布式AKF拆分原则

目录 1 前言2 什么是AKF3 如何基于 AKF X 轴扩展系统&#xff1f;4 如何基于 AKF Y 轴扩展系统&#xff1f;5 如何基于 AKF Z 轴扩展系统&#xff1f;6 小结 1 前言 当我们需要分布式系统提供更强的性能时&#xff0c;该怎样扩展系统呢&#xff1f;什么时候该加机器&#xff1…

网络安全(黑客)技术自学

前言 一、什么是网络安全 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域&#xff0c;都有攻与防…

高忆管理:突破22万亿!五大保险巨头总资产创历史新高

阅历了几年深度转型的稳妥业正在冲破迷雾。 券商我国记者统计显现&#xff0c;本年上半年&#xff0c;我国人寿、我国人保、我国安全、我国太保、新华稳妥等五大A股上市险企总财物破22万亿元&#xff0c;半年度营收1.5万亿元。从3至5年中长周期来看&#xff0c;稳妥集团公司体…

【大数据】Kafka 入门指南

Kafka 入门指南 1.Kafka 简介2.Kafka 架构3.分区与副本4.偏移量5.消费者组6.总结 1.Kafka 简介 Apache Kafka 是一种高吞吐、分布式的流处理平台&#xff0c;由 LinkedIn 开发并于 2011 年开源。它具有 高伸缩性、高可靠性 和 低延迟 等特点&#xff0c;因此在大型数据处理场景…

“JSR303和拦截器在Java Web开发中的应用与实践“

目录 引言JSR303什么是JSR303?为什么要使用JSR303?常用注解快速入门JSR303 拦截器什么是拦截器拦截器与过滤器应用场景快速入门拦截器 总结 引言 在Java Web开发过程中&#xff0c;我们经常会遇到需要对输入数据进行验证和处理&#xff0c;同时需要对请求进行拦截与控制的需…

纷享销客受邀出席CDIE2023数字化创新博览会 助力大中型企业增长

2023年&#xff0c;穿越周期&#xff0c;用数字化的力量重塑企业经营与增长的逻辑&#xff0c;再次成为企业数字化技术应用思考的主旋律&#xff0c;以数字经济为主线&#xff0c;数字技术融入产业发展与企业增长为依据&#xff0c;推动中国企业数字化升级。 9月5日&#xff0c…

Git多人开发解决冲突案例

准备工作&#xff1a; 1.创建一个gitee远程仓库https://gitee.com/xxxxxxx.git 2.初始化两个本地git仓库用户&#xff0c;目的是模拟多人协作开发时提交代码发生冲突的场景 3.解决冲突并提交。 进入正题&#xff1a; lisi 通过vim指令修改readme.md文件内容&#xff0c;推送到…

合宙Air724UG LuatOS-Air LVGL API控件-表格(Table)

表格&#xff08;Table&#xff09; 示例代码 --创建表格Table1 lvgl.table_create(lvgl.scr_act(),nil)--设置表格为4行5列lvgl.table_set_row_cnt(Table1,4)lvgl.table_set_col_cnt(Table1,5)--给每个单元格赋值lvgl.table_set_cell_value(Table1, 0, 0, "选手")l…

QT生成ICO文件

生成ICO文件 #include <QApplication> #include <QImage> #include <QIcon> #include <QFile> #include <QDebug> #include <QPixmap>int main(int argc, char* argv[]) {QApplication app(argc, argv);// 读取图片文件QImage image(&quo…

Python类的概念

类 类的技术名词解释 ● 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。 ● 类变量&#xff1a;类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用…

功率放大器的定义详解

功率放大器是一种电子放大器&#xff0c;主要用于将输入信号的功率放大到足以驱动负载或输出器件所需的水平。通常&#xff0c;功率放大器会将低电平高电流的输入信号转换成高电平低电流的输出信号&#xff0c;以便给负载提供足够的功率。 功率放大器广泛应用于各种应用场合&am…

(Note)中文EI检索期刊目录

ei和sci、ssci一样是国际知名的期刊数据库&#xff0c;ei不仅收录国际知名的刊物&#xff0c;也收录了一些国内期刊&#xff0c;为方便投稿选刊&#xff0c;Elsevier官网更新了的EI Compendex期刊目录&#xff0c;那么 国内ei期刊有哪些? 经查询共有250余种期刊&#xff0c;新…

【LeetCode-面试经典150题-day23】

目录 108. 将有序数组转换为二叉搜索树 148.排序链表 427.建立四叉树 23.合并K个升序链表 108. 将有序数组转换为二叉搜索树 题意&#xff1a; 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 高度平衡 二叉搜索树。 高度平衡 二…