观察者模式-C++

news2024/11/26 4:43:06

观察者模式(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;
}

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

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

适用场景:

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

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

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

相关文章

关于三维模型几何坐标修正的技术方法探究

关于三维模型几何坐标修正的技术方法探究 倾斜摄影三维模型的几何坐标修正是保证模型准确性和一致性的重要步骤。下面将探讨几种常见的技术方法用于倾斜摄影三维模型几何坐标修正。 1、块内坐标转换&#xff1a;在倾斜摄影中&#xff0c;可以将整个场景划分为多个块&#xff0…

Ubuntu之apt更换国内镜像源

一、需求说明 Ubuntu系统默认使用的是Ubuntu官网镜像源http://archive.ubuntu.com&#xff0c;网站位于境外&#xff0c;我们使用apt安装软件包的时候经常出现无法连接的情况&#xff0c;如下图所示。所以建议将系统apt安装的镜像源切换为国内镜像源。 二、更新apt镜像源步骤…

【入门Flink】- 11Flink实现动态TopN

基本处理函数&#xff08;ProcessFunction&#xff09; stream.process(new MyProcessFunction())方法需要传入一个 ProcessFunction 作为参数&#xff0c;ProcessFunction 不是接口 &#xff0c; 而是一个抽象类 &#xff0c;继承了AbstractRichFunction&#xff0c;所有的处…

保护您的Google账号安全:检查和加固措施

简介&#xff1a;随着我们在日常生活中越来越依赖于Google账号&#xff0c;我们的个人信息和敏感数据也变得越来越容易受到威胁。为了确保您的Google账号的安全性&#xff0c;本文将介绍一些简单但有效的方法&#xff0c;帮助您检查和加固您的Google账号。 --- 在数字时代&am…

【Linux】Linux基础IO(上)

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;Linux &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 上一篇博客&#xff1a;【Linux】…

CSRF 跨站请求伪造漏洞理解

1.漏洞描述 跨站请求伪造是一种攻击&#xff0c;它强制浏览器客户端用户在当前对其进行身份验证后的Web应用程序上执行非本意的操作&#xff0c;攻击的重点在处于更改状态请求&#xff0c;而不是盗取数据&#xff0c;因为攻击者无法查看伪造请求的响应。 2.漏洞原理 攻击者可以…

【GlobalMapper精品教程】064:点云提取(按范围裁剪)

本文讲解Globalmapper中进行点云数据提取(按范围裁剪)的方法。 文章目录 一、加载点云及范围数据二、点云裁剪三、注意事项一、加载点云及范围数据 加载配套实验数据包中的实验数据data064.rar中的point.las点云与bound.shp面状范围数据,如下图所示: 二、点云裁剪 接下来…

光明源@为什么需要智慧厕所,智慧厕所是干什么的?

在当今数字化时代&#xff0c;城市的发展日新月异&#xff0c;城市居民对生活品质和城市服务的期望也与日俱增。在城市规划和基础设施建设中&#xff0c;智慧厕所作为一项创新性的举措&#xff0c;正逐渐崭露头角。本文将探讨为什么需要智慧厕所以及它们的实际功能和意义。 城市…

OpenAI API-KEY如何获取购买,推荐使用卡密自助发货更方便

在信息爆炸的时代&#xff0c;人们面临海量信息的洪流&#xff0c;其中蕴含了无尽的知识和见解。AI垂直问答技术的兴起&#xff0c;应运而生于这一背景下。与传统的搜索引擎不同&#xff0c;垂直问答聚焦于特定领域&#xff0c;通过深度学习和自然语言处理技术&#xff0c;为用…

Xilinx Kintex7中端FPGA解码MIPI视频,基于MIPI CSI-2 RX Subsystem架构实现,提供工程源码和技术支持

目录 1、前言免责声明 2、我这里已有的 MIPI 编解码方案3、本 MIPI CSI2 模块性能及其优缺点4、详细设计方案设计原理框图OV5640及其配置权电阻硬件方案MIPI CSI-2 RX SubsystemSensor Demosaic图像格式转换Gammer LUT伽马校正VDMA图像缓存AXI4-Stream toVideo OutHDMI输出 5、…

巅峰之作TFN AMT系列手持式信号综合测试仪

手持式信号综合测试仪是对无线电信号进行测量的必备手段&#xff0c;是从事电子产品研发、生产、检验的常用工具。因此&#xff0c;应用十分广泛&#xff0c;被称为工程师的射频万用表。传统的频谱分析仪的前端电路是一定带宽内可调谐的接收机&#xff0c;输入信号经变频器变频…

LeetCode | 20. 有效的括号

LeetCode | 20. 有效的括号 OJ链接 这道题可以使用栈来解决问题~~ 思路&#xff1a; 首先我们要使用我们之前写的栈的实现来解决此问题~~如果左括号&#xff0c;就入栈如果右括号&#xff0c;出栈顶的左括号跟右括号判断是否匹配 如果匹配&#xff0c;继续如果不匹配&#…

11.13堆的各种操作算法,二叉树的一些性质

算法 二叉堆的上调 在树上进行的插入排序 。循环次数不会超过树的高度&#xff0c;即插入交换次数不会超过ologn&#xff0c;n是结点个数 要么到根节点&#xff0c;即i1结束&#xff0c;要么当前元素还比上面的元素小&#xff0c;直到不比上面的元素小&#xff0c;即h[i/2]&l…

Windows系统隐藏窗口启动控制台程序

背景 上线项目有时候需要一些控制台应用作为辅助服务来协助UI应用满足实际需求&#xff0c;这时候如果一运行UI就冒出一系列的黑框&#xff0c;这将会导致客户被下的不起&#xff0c;生怕中了什么不知名病毒 方案 可以使用vbs来启动&#xff0c;这个是window系统自带的&#…

(免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐

摘 要 本论文主要论述了如何使用Django开发一个校园宿舍管理系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述校园宿舍管理系统的当前背景以及系统开发的目的…

简单地聊一聊Spring Boot的构架

本文由葡萄城技术团队发布。转载请注明出处&#xff1a;葡萄城官网&#xff0c;葡萄城为开发者提供专业的开发工具、解决方案和服务&#xff0c;赋能开发者。 前言 本文小编将详细解析Spring Boot框架&#xff0c;并通过代码举例说明每个层的作用。我们将深入探讨Spring Boot的…

asp.net实验管理系统VS开发sqlserver数据库web结构c#编程web网页设计

一、源码特点 asp.net 实验管理系统 是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语言开发。 asp.net实验管理系统1 应用技术&am…

初学UE5 C++①

游戏类 1.创建所需项的类 2.创建游戏模式类&#xff0c;在该类上实现所需项&#xff0c;引入头文件和构造函数时实例化 三种时间函数类型函数和提示类型 FName、FString、FText类型相互转化 FName用FName FString用ToString&#xff08;&#xff09; FText用FText&#xff1a;…

【nlp】2.1 认识RNN模型

认识RNN模型 1 什么是RNN模型2 RNN模型的作用3 RNN模型的分类:1 什么是RNN模型 RNN(Recurrent Neural Network),,中文称作循环神经网络,它一般以序列数据为输入, 通过网络内部的结构设计有效捕捉序列之间的关系特征,一般也是以序列形式进行输出。 一般单层神经网络结构:…

SAP-SD-外向交货单交期不符

创建外向交货单时报错 销售订单的交期还没到&#xff0c;所以不能做外向交货单 但是货已经加工完成&#xff0c;现在想交货 查看销售订单的交货期为12月15日&#xff08;va03&#xff09; 在VL01N里修改“选择日期为12月15日”就可以了。