观察者模式-C++

观察者模式(Observer)是一种行为型设计模式,它用于在对象之间建立一对多的依赖关系,当一个对象发生改变时,所有依赖它的对象都会收到通知进行相应的改变。

观察者模式中有两种核心角色:

  • 观察者(Observer):也被称为订阅者或监听者,观察者通过注册到特定的主题上,当主题的状态发生改变时,它可以收到这种变化更新自身状态。观察者定义了一个统一的接口,使得主题可以通过接口将通知发送给所有的观察者。
  • 主题(Subject):也称为被观察者,它管理着一组观察者对象,提供添加、删除观察者对象的方法。当主题发生改变的时候可以将通知发送给所有的观察者对象。

在这里面,观察者依赖主题,所以一个主题可以对应多个观察者。

观察者模式的流程:

  • 主题对象管理观察者对象的添加和删除
  • 主题对象维护一个观察者对象的列表,用于记录所有注册的观察者对象
  • 当主题对象的状态发生改变时,遍历观察者列表,将通知发送给每一个观察者对象
  • 观察者对象收到通知后更新自身的状态

观察者模式也有三个组件:观察者接口、观察者、主题

举例:
假设现在我们有一个电子商务平台,当用户下单之后我们希望通知库存系统和用户通知系统。

现在我们按照观察者模式的三个组件来编写代码:观察者接口、观察者、主题

// 观察者接口
class IObserver
{
public:

	virtual ~IObserver(){}

	virtual void Update(const std::string& _msg) = 0;
};

// 观察者-库存系统
class InventorySystem
	: public IObserver
{
public:

	virtual void Update(const std::string& _msg) override
	{
		std::cout << "库存系统:" << _msg << std::endl;
	}
};

// 观察者-用户通知系统
class UserNotifySystem
	: public IObserver
{
public:

	virtual void Update(const std::string& _msg) override
	{
		std::cout << "用户通知系统:" << _msg << std::endl;
	}
};

// 主题
class Subject
{
public:

	// 添加观察者对象
	void AddObserver(std::shared_ptr<IObserver> _observer)
	{
		if (_observer)
			observers_.push_back(_observer);
	}

	// 删除观察者对象
	void RemoveObserver(std::shared_ptr<IObserver> _observer)
	{
		for (auto it = observers_.begin(); it != observers_.end();)
		{
			if (*it == _observer)
				it = observers_.erase(it);
			else
				it++;
		}
	}

	// 用户下单
	void UserPlatform(const std::string& _msg)
	{
		std::cout << "用户下单:" << _msg << std::endl;

		NotifyAllObserver(_msg);
	}

private:

	// 通知所有的观察者对象
	void NotifyAllObserver(const std::string _msg)
	{
		for (auto it : observers_)
			it->Update(_msg);
	}

private:

	// 记录所有注册的观察者对象
	std::list<std::shared_ptr<IObserver>> observers_;
};

在main.cpp里使用它:

void TestObserver()
{
	// 主题对象
	std::shared_ptr<Subject> subject = std::make_shared<Subject>();

	// 观察者对象-库存系统
	std::shared_ptr<IObserver> inventory_system = std::make_shared<InventorySystem>();

	// 观察者对象-用户通知系统
	std::shared_ptr<IObserver> user_notify = std::make_shared<UserNotifySystem>();

	// 注册观察者
	subject->AddObserver(inventory_system);
	subject->AddObserver(user_notify);

	// 用户下单
	subject->UserPlatform("iphone 11");

	std::cout << "---------------------删除 用户通知系统------------------" << std::endl;

	// 删除观察者
	subject->RemoveObserver(user_notify);

	// 用户下单
	subject->UserPlatform("小米 11");
}

int main()
{
    // 策略模式用法
	// TestStrategy();

	TestObserver();

    system("pause");
    return 0;
}

输出:
在这里插入图片描述优点:

  • 松耦合:主题和观察者之间是松耦合的,修改一个观察者对象不影响其他对象
  • 可扩展:可以在任何时候添加和删除观察者,无需修改已有代码
  • 即时通知:一旦主题发生改变,观察者可以立即收到通知。

适用场景:

  • 当一个对象发生改变时,希望主动通知其他对象而不是其他对象等待通知时
  • 当具有一对多的关系时,一个对象的更新会影响到其他对象时

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

面试:容器技术

目录 为什么需要 DevOpsDocker 是什么&#xff1f;Docker 与虚拟机有何不同&#xff1f;什么是 Docker 镜像&#xff1f;什么是 Docker 容器&#xff1f;Docker 容器有几种状态&#xff1f;解释一下 Dockerfile 的 ONBUILD 指令&#xff1f;什么是 Docker Swarm&#xff1f;如何…

解决npm报错Error: error:0308010C:digital envelope routines::unsupported

解决npm报错Error: error:0308010C:digital envelope routines::unsupported。 解决办法&#xff1b;终端执行以下命令&#xff08;windows&#xff09;&#xff1a; set NODE_OPTIONS--openssl-legacy-provider然后再执行 npm命令成功&#xff1a;

一个关于jdbc操作mysql和java基础练手的通讯录管理系统小项目

首先 : 整个项目的项目结构为 : 1.第一步先导入数据库的驱动&#xff0c;我的mysql数据库是8.0以上版本&#xff0c;然后导入的驱动就是8.0.16版本的jar包&#xff1b; 1.JdbcBase : JDBC基础操作封装成了JdbcBase类,在里面先静态定义了数据库连接对象和DQL查询结果&#x…

打开 Chrome 的 「内存节省程序」开关和关闭硬件加速

不知道从什么时候开始&#xff0c;应该是最近1个月&#xff0c;感觉 Mac 浏览器总是占用很高的 CPU&#xff0c;多开一些标签页&#xff0c;或者浏览器窗口&#xff0c;相互切换时系统就会变得无响应&#xff0c;从 Chrome 浏览器里找到一个「内存节省程序」的配置&#xff0c;…

MATLAB算法实战应用案例精讲-【数模应用】漫谈机器学习(二)

目录 几个高频面试题目 机器学习中的模型评价、模型选择与算法选择 基本的模型评估项和技术 Bootstrapping 和不确定性 交叉验证和超参数优化 机器学习的发展历程 知识储备 机器学习常用术语 算法原理 1. 什么是机器学习&#xff1f; 机器学习和人工智能的关系 机…

数据校验:Spring Validation

Spring Validation概述 在开发中&#xff0c;我们经常遇到参数校验的需求&#xff0c;比如用户注册的时候&#xff0c;要校验用户名不能为空、用户名长度不超过20个字符、手机号是合法的手机号格式等等。如果使用普通方式&#xff0c;我们会把校验的代码和真正的业务处理逻辑耦…

开源网安受邀参加网络空间安全合作与发展论坛,为软件开发安全建设献计献策

​11月10日&#xff0c;在广西南宁举办的“2023网络空间安全合作与发展论坛”圆满结束。论坛在中国兵工学会的指导下&#xff0c;以“凝聚网络空间安全学术智慧&#xff0c;赋能数字经济时代四链融合”为主题&#xff0c;邀请了多位专家及企业代表共探讨网络安全发展与数字经济…

文件操作(上)

目录 为什么使用文件什么是文件&#xff1f;程序文件数据文件文件名 二进制文件和文本文件文件的打开和关闭流和标准流流标准流 文件指针文件的打开和关闭 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 &#x1f412;&#x1f412;&#x1f412; 个人主页 &…

08【保姆级】-GO语言的函数、包、错误处理

08【保姆级】-GO语言的函数、包、错误处理 一、 函数基本介绍1.1 基本概念1.2 包的概念1.3 包使用的注意事项和细节1.4 函数的调用机制1.5 函数的递归调用1.6 函数使用的注意事项和细节讨论1.7 init函数1.8 匿名函数1.8.1 匿名函数使用方式1.8.2 全局匿名函数 1.9 闭包1.9.1 闭…

0基础学习PyFlink——水位线(watermark)触发计算

在《0基础学习PyFlink——个数滚动窗口(Tumbling Count Windows)》和《0基础学习PyFlink——个数滑动窗口&#xff08;Sliding Count Windows&#xff09;》中&#xff0c;我们发现如果窗口中元素个数没有把窗口填满&#xff0c;则不会触发计算。 为了解决长期不计算的问题&a…

Docker安装详细步骤及相关环境安装配置(mysql、jdk、redis、自己的私有仓库Gitlab 、C和C++环境以及Nginx服务代理)

目录 一、从空白系统中克隆Centos7系统 二、使用xshell连接docker_tigerhhzz虚拟机​编辑 三、在CentOS7基础上安装Docker容器 四、在Docker中进行安装Portainer 4.1、在Docker中安装MySQL 4.2、在Docker中安装JDK8&#xff0c;安装Java环境 4.3、Docker安装redis&#…

聚观早报 |京东11.11公布成绩单;2023数字科技生态大会

【聚观365】11月13日消息 京东11.11公布成绩单 2023数字科技生态大会 TikTok深受英国中小企业青睐 周鸿祎称大模型2年内可“进”智能汽车 双11全国快递业务量达 6.39 亿件 京东11.11公布成绩单 京东11.11公布成绩单&#xff1a;截至11月11日晚23:59&#xff0c;2023年京东…

桌面云架构讲解(VDI、IDV、VOI/TCI、RDS)

目录 云桌面架构 VDI 虚拟桌面基础架构 IDV 智能桌面虚拟化 VOI/TCI VOI 虚拟系统架构 TCI 透明计算机架构 RDS 远程桌面服务 不同厂商云桌面架构 桌面传输协议 什么是云桌面 桌面云是虚拟化技术成熟后发展起来的一种应用&#xff0c;桌面云通常也称为云桌面、VDI等 …

OpenCV 笔记(6):像素间的基本关系——邻域、邻接、通路、连通、距离

像素是图像的基本元素&#xff0c;像素与像素之间存在着某些联系&#xff0c;理解像素间的基本关系是数字图像处理的基础。常见的像素间的基本关系包括&#xff1a;邻域、邻接、通路、连通、距离。 Part11. 邻域 邻域表示了像素之间的连接关系。 像素(x,y)的邻域&#xff0c;是…

计算机二级Office真题解析 excel减免税,订单,成绩

第一题 1.将“Excel 减免税.xlsx”文件另存为 excel.xlsx&#xff0c;最后提交该文件&#xff08;1 分&#xff09;。 2.将“对应代码.xlsx”文件中的 sheet1 工作表插入到 excel.xlsx 中&#xff0c;工作 表名重命名为“代码”&#xff08;3 分&#xff09;。 3.在"序号&…

从关键新闻和最新技术看AI行业发展(2023.10.23-11.5第九期) |【WeThinkIn老实人报】

Rocky Ding 公众号&#xff1a;WeThinkIn 写在前面 【WeThinkIn老实人报】旨在整理&挖掘AI行业的关键新闻和最新技术&#xff0c;同时Rocky会对这些关键信息进行解读&#xff0c;力求让读者们能从容跟随AI科技潮流。也欢迎大家提出宝贵的优化建议&#xff0c;一起交流学习&…

将随机数设成3407,让你的深度学习模型再涨一个点!文再附3种随机数设定方法

随机数重要性 深度学习已经在计算机视觉领域取得了巨大的成功&#xff0c;但我们是否曾想过为什么同样的模型在不同的训练过程中会有不同的表现&#xff1f;为什么使用同样的代码&#xff0c;就是和别人得到的结果不一样&#xff1f;怎么样才能保证自己每次跑同一个实验得到的…

Django中Cookie和Session的使用

目录 一、Cookie的使用 1、什么是Cookie&#xff1f; 2、Cookie的优点 3、Cookie的缺点 4、Django中Cookie的使用 二、Session的使用 1、什么是Session&#xff1f; 2、Session的优点 3、Session的缺点 4、Django中Session的使用 三、Cookie和Session的对比 总结 D…

Vue 小黑记事本组件板

渲染功能&#xff1a; 1.提供数据&#xff1a; 提供在公共的父组件 App.vue 2.通过父传子&#xff0c;将数据传递给TodoMain 3.利用 v-for渲染 添加功能&#xff1a; 1.收集表单数据 v-model 2.监听事件&#xff08;回车点击都要添加&#xff09; 3.子传父&#xff0c;讲…

【嵌入式设计】Main Memory:SPM 便签存储器 | 缓存锁定 | 读取 DRAM 内存 | DREM 猝发(Brust)

目录 0x00 便签存储器&#xff08;Scratchpad memory&#xff09; 0x01 缓存锁定&#xff08;Cache lockdown&#xff09; 0x02 读取 DRAM 内存 0x03 DREM Banking 0x04 DRAM 猝发&#xff08;DRAM Burst&#xff09; 0x00 便签存储器&#xff08;Scratchpad memory&#…