C++ 大话设计之《观察者模式》(优缺点,设计原理,常用场景)

2023-11-13

观察者模式是一种行为型模式


 

优点:

  • 松散耦合:观察者模式提供了一种松散耦合的设计,使得当一个对象的状态发生变化时,它不需要知道其他对象是如何使用这些信息的。这使得系统更容易扩展和维护。
  • 动态关联:观察者模式允许在运行时动态地添加或删除观察者,而无需修改主题或其他观察者的代码。
  • 抽象耦合:由于主题和观察者之间仅通过抽象接口进行通信,因此它们之间的耦合是抽象的,而不是具体的。

缺点:

  • 可能导致意外的更新:如果一个观察者在接收到通知后执行了一些操作,这些操作又导致了主题状态的变化,那么就可能会导致意外的更新。
  • 可能导致性能问题:如果有大量的观察者需要更新,那么通知所有观察者可能会导致性能问题。
  • 可能增加复杂性:如果没有正确实现,观察者模式可能会增加系统的复杂性。

满足的设计原则:

  • 单一职责原则(SRP):观察者模式允许将观察者和被观察者分离,使它们能够独立更改和复用。这样,每个类都只需要关注自己的职责,而不需要关心其他类的实现细节。
  • 开放封闭原则(OCP):观察者模式允许在不修改现有代码的情况下添加新的观察者。这样,系统可以在不影响现有功能的情况下扩展。
  • 依赖倒置原则(DIP):观察者模式中,主题和观察者之间仅通过抽象接口进行通信,而不是直接依赖于具体实现。
  • 这样,高层模块(被观察者)不依赖于低层模块(观察者),而是依赖于抽象接口。
     

常用实例:

  • 当一个对象的状态发生变化时,需要通知其他对象。例如,在文本编辑器中,当用户在文本框中输入文本时,文本框会通知其他组件(如字数统计器或拼写检查器)更新其状态。
  • 当一个对象的状态发生变化时,需要执行一些动作。例如,在电子商务网站中,当用户将商品添加到购物车时,购物车会通知库存管理系统更新库存。
  • 当需要在多个对象之间实现松散耦合的设计时。例如,在MVC架构中,模型(Model)会通知视图(View)更新其显示内容,但模型并不需要知道视图是如何使用这些信息的。
     

类图:

代码: 

#include "iostream"
#include "string"
#include <list>


using namespace std;

class Observer;


//抽象被观察者
class Subject
{
public:
	Subject():m_nState(0){}
	virtual ~Subject()=default;

	
	//增加观察者
	virtual void Attach(Observer* pObserver)=0;

	//移除观察者
	virtual void Detach(Observer* observer)=0;

	//通知
	virtual void Notify()=0;

	virtual int GetState()
	{
		return m_nState;
	}

	void SetState(int state)
	{
		cout<<"Subjeceet updated!"<<endl;
		m_nState	=state;
	}


	list<Observer*> m_pObserver_list;
	int m_nState;

};
//抽象观察者

/*

*/

class Observer
{
public:
	
	virtual ~Observer()=default;
		
	Observer( Subject* pSubject,const string &name="unknown"):m_pSubject(pSubject),m_strName(name){}

	virtual void Update()=0;

	virtual const string& name()
	{
		return m_strName;
	}

protected:
	Subject *m_pSubject;
	string m_strName;
};

//具体被观察者
class ConcreteSubject :public Subject
{
public:
	void Attach(Observer* pObserver)
	{
		cout<<"Attach observer"<<pObserver->name()<<endl;
		m_pObserver_list.push_back(pObserver);
	};

	 void Detach(Observer* pObserver) 
	{
		cout<<"Detach observer"<<pObserver->name()<<endl;
		m_pObserver_list.remove(pObserver);
	};

	 void Notify()
	{
		for (list<Observer*>::iterator iter = m_pObserver_list.begin(); iter != m_pObserver_list.end(); ++iter)
		{
			(*iter)->Update();
		}
	}
};

//具体观察者1
class Observer1 :public Observer
{
public:
	Observer1(Subject*pSubject,const string& name="unknown"):Observer(pSubject,name){}

	void Update() 
	{
		cout<<"Observer1_"<<m_strName<<"get the upda.new state is:"<<m_pSubject->GetState()<<endl;
	};
};

//具体观察者2
class Observer2 :public Observer
{
public:
	Observer2(Subject* pSubject, const string& name = "unknown") :Observer(pSubject, name) {}

	void Update()
	{
		cout << "Observer2_" << m_strName << "get the upda.new state is:" << m_pSubject->GetState() << endl;
	};
};

int main()
{
	Subject *pSubject=new ConcreteSubject;
	
	Observer *pObserver_1=new Observer1(pSubject,"1");
	Observer *pObserver_2=new Observer1(pSubject,"2");

	Observer* pObserver_3 = new Observer2(pSubject, "3");
	Observer* pObserver_4 = new Observer2(pSubject, "4");
	
	//注册观察者
	pSubject->Attach(pObserver_1);
	pSubject->Attach(pObserver_2);
	pSubject->Attach(pObserver_3);
	pSubject->Attach(pObserver_4);
	//pSubject->SetState(3);



	pSubject->Notify();


	return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 大话设计之《观察者模式》(优缺点,设计原理,常用场景) 的相关文章

  • 在 Vulkan 中,图形队列系列与当前队列系列分离是否有益?

    据我所知 队列系列可能支持呈现到屏幕但不支持图形 假设我有一个同时支持图形和呈现的队列系列 以及另一个仅支持呈现的队列系列 我应该为两个进程使用第一个队列系列 还是应该将第一个队列系列委托给图形 将后者委托给呈现 或者这两种方法之间没有明显
  • 与 for_each 或 std::transform 一起使用时,如何调用 C++ 函子构造函数

    我以前从未使用过 C 函子 所以我只是想了解它们是如何工作的 例如假设我们有这个函子类 class MultiplyBy private int factor public MultiplyBy int x factor x int ope
  • 捕获 .aspx 和 .ascx 页面中的异常

    问题说明了一切 请看以下示例代码 ul li li ul
  • 为什么 C 程序使用 Scanf 给出奇怪的输出?

    我目前正在学习 C 编程 并且遇到了这个奇怪的输出 Program will try functionalities of the scanf function include
  • Boost ASIO 串行写入十六进制值

    我正在使用 ubuntu 通过串行端口与设备进行通信 所有消息都必须是十六进制值 我已经在 Windows 环境中使用白蚁测试了通信设置 并得到了我期望的响应 但在使用 Boost asio 时我无法得到任何响应 以下是我设置串口的方法 b
  • 如何修复错误:“检测到无法访问的代码”

    我有以下代码 private string GetAnswer private int CountLeapYears DateTime startDate return count String answer GetAnswer Respo
  • 用于在标头更改时重新编译的简单 C 项目的示例 makefile

    有谁有完整的 makefile 可以执行以下操作 如果 HEADER 文件发生更改 则重建项目 cpp 文件在 makefile 中列出 头文件未在 makefile 中列出 头文件允许与 cpp 文件具有不同的名称 部分cpp文件没有头文
  • Linux 上的 RTLD_LOCAL 和dynamic_cast

    我们有一个由应用程序中的一些共享库构成的插件 我们需要在应用程序运行时更新它 出于性能原因 我们在卸载旧插件之前加载并开始使用新插件 并且只有当所有线程都使用旧插件完成后 我们才卸载它 由于新插件和旧插件的库具有相同的符号 我们dlopen
  • C# 获取数据表中所有重复行的计数

    我通过运行存储过程来填充数据集 并且从数据集中填充数据表 DataSet RawDataSet DataAccessHelper RunProcedure storedprocedureName this will just return
  • 让网络摄像头在 OpenCV 中工作

    我正在尝试让我的网络摄像头在 Windows 7 64 位中的 OpenCV 版本 2 2 中捕获视频 但是 我遇到了一些困难 OpenCV 附带的示例二进制文件都无法检测到我的网络摄像头 最近我发现这篇文章表明答案在于重新编译一个文件 o
  • 对于 C# Express 用户来说,有哪些好的工具可以识别可能重复的代码? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 也可以看看 有什么工具可以检查重复的 VB NET 代码吗 https stackoverflow c
  • ASP.NET Core 中间件与过滤器

    在阅读了 ASP NET Core 中间件之后 我对何时应该使用过滤器以及何时应该使用中间件感到困惑 因为它们似乎实现了相同的目标 什么时候应该使用中间件而不是过滤器 9频道有一个关于此的视频 ASP NET 怪物 91 中间件与过滤器 h
  • 读取依赖步行者输出

    I am having some problems using one of the Dlls in my application and I ran dependency walker on it i am not sure how to
  • .NET 和 Mono 之间的开发差异

    我正在研究 Mono 和 NET C 将来当项目开发时我们需要在 Linux 服务器上运行代码 此时我一直在研究 ASP NET MVC 和 Mono 我运行 Ubuntu 发行版 想要开发 Web 应用程序 其他一些开发人员使用 Wind
  • Unity3D - 将 UI 对象移动到屏幕中心,同时保持其父子关系

    我有一个 UI 图像 它的父级是 RectTransform 容器 该容器的父级是 UI 面板 而 UI 面板的父级是 Canvas 我希望能够将此 UI 图像移动到屏幕中心 即画布 同时保留父级层次结构 我的目标是将 UI 图像从中心动画
  • 如何从 Windows Phone 7 模拟器获取数据

    我有一个 WP7 的单元测试框架 它在手机上运行 结果相当难以阅读 因此我将它们写入 XDocument 我的问题是 如何才能将这个 XML 文件从手机上移到我的桌面上 以便我可以实际分析结果 到目前为止 我所做的是将 Debugger B
  • 如何获取带有某个属性注释的所有属性?

    我刚刚从 Roslyn 开始 我想找到所有用属性名称 OneToOne 注释的属性 我启动了 SyntaxVisualizer 并能够获取对该节点的引用 但我想知道是否有更简单的方法来实现此目的 这就是我所拥有的 var prop docu
  • 从后面的代码添加外部 css 文件

    我有一个 CSS 文件 例如 SomeStyle css 我是否可以将此样式表文档从其代码隐藏应用到 aspx 页面 您可以将文字控件添加到标头控件中 Page Header Controls Add new System Web UI L
  • ContentDialog Windows 10 Mobile XAML - 全屏 - 填充

    我在项目中放置了一个 ContentDialog 用于 Windows 10 上的登录弹出窗口 当我在移动设备上运行此项目时 ContentDialog 未全屏显示 并且该元素周围有最小的填充 在键盘上可见 例如在焦点元素文本框上 键盘和内
  • 如何为有时异步的操作创建和实现接口

    假设我有数百个类 它们使用 计算 方法实现公共接口 一些类将执行异步 例如读取文件 而实现相同接口的其他类将执行同步代码 例如将两个数字相加 为了维护和性能 对此进行编码的好方法是什么 到目前为止我读到的帖子总是建议将异步 等待方法冒泡给调

随机推荐

  • java的3大注释快捷键大全

    单行注释 行注释 一般用于单行或者少量代码 快捷键 光标 ctrl 或者 多行注释 块注释 一般用于多行或者大量代码 快捷键 选中 ctrl shift 文档注释 方法或类注释 一般用于对类和方法的说明 快捷键 光标 回车键 EnTer
  • 蓝桥杯Java必备基础知识总结大全【3W字】持续更新中

    本文会持续更新 如果对您有帮助的话可以点点关注 双击 本人2021年蓝桥杯C B组国二 今年转战Java 并整理此文 希望能够对大家有所帮助 第一次写这么长的文章 可能有的地方写的不是很好 还请大家多多谅解 我会持续进行改进并且更新 更新
  • 海思(MPP)媒体处理软件平台(3)-----VDEC

    sample vdec 视频解码 测试环境 在HI3531D开发板上运行 查看代码使用VSCode 运行 nfsroot mpp sample vdec sample vdec please choose the case which yo
  • [激光原理与应用-68]:光耦继电器、固态继电器、延时继电器、PLC开关信号

    一 PLC开关信号 备注 PLC需要的是开关信号 闭合或断开 不需要TTL电平信号 二 激光器输出信号 三 固态激光器工作原理 四 光耦继电器原理 五 光耦 延时 继电器原理 六 差分转单端原理
  • 排列组合知识

    排列组合的定义 排列 就是从n个元素中取出m个元素 按照一定的顺序排成一列 看到没 是要有顺序排成一列的 组合 也是从n个元素中取出m个元素 只不过是组成一个组 并不要求排成一列 只要组的成员不同就可以了 公式如下 例题 哪里用得上排列组合
  • 【Markdown】图片缩放

    01 原图表示 语法为 替代文本 图片链接地址 其中 替代文本是在无法显示图片时显示的替代文本 而图片链接是指向图片的URL或相对路径 例如 插入Panda图片 panda https img blog csdnimg cn e5f32e4
  • 亚信科技AntDB数据库专家参加向量数据库首次技术标准研讨会

    2023年7月19日下午 中国通信标准化协会大数据技术标准推进委员会数据库与存储工作组 CCSA TC601 WG4 联合中国信通院数据库应用创新实验室 CAICT DBL 在线上召开 向量数据库技术要求 标准首次研讨会 本次会议由中国信通
  • 单端反激——隔离型DC/DC变换器的设计及仿真

    单端反激 隔离型DC DC变换器的设计及仿真 技术指标 1 原理分析 2 参数设计 3 仿真验证 技术指标 输入电压 V s m i n
  • Spring Boot 2.2.6 源码之旅二十五SpringMVC源码之RequestMappingHandlerMapping的初始化三

    Spring Boot 2 2 6 源码之旅二十五SpringMVC源码之RequestMappingHandlerMapping的初始化三 简单流程图 MappingRegistry的一些映射 urlLookup一键多值的url和Requ
  • 那些会阻碍程序员成长的细节[4]

    照例 如果没有读过之前的系列 在这里可以先回顾一下 那些会阻碍程序员成长的细节 1 那些会阻碍程序员成长的细节 2 那些会阻碍程序员成长的细节 3 本文共 1637 字 预计阅读时间 5 分钟 不愿意跟领导走的近 是不是有这样的体会 凡事有
  • 【python标准库学习】re模块

    1 什么是re 正则表达式一门相对通用的语言 在python中也有对正则表达式的支持 那就是的内置re模块 正则表达式就是一系列的规则去匹配字符串然后进行相应的操作 这些规则网上一搜一大片 而re则是运用正则表达式来提供一系列的功能强大的接
  • Vue中如何进行打包与部署?

    Vue中如何进行打包与部署 Vue是一款流行的JavaScript框架 它提供了丰富的功能和组件 可以用于构建现代化的Web应用程序 在开发Vue应用程序时 我们通常需要进行打包和部署 本文将介绍Vue中的打包和部署 包括使用Webpack
  • STL list合并

    知识点来源 cplusplus STL list 网上很多关于list的操作很少有提及到怎么合并 要说这个合并几乎是每个数据结构课提及到的O 1 操作的必修知识点 同时还有人甚至搞不清楚什么叫Merge 归并 和合并 Union 归并的意思
  • linux 查看端口连接数

    一 查看哪些IP连接本机 netstat an 二 查看TCP连接数 1 统计80端口连接数 netstat nat grep i 80 wc l 2 统计httpd协议连接数 ps ef grep httpd wc l 3 统计已连接上的
  • 高斯列主消元法 求非齐次线性方程组 C语言实现代码

    高斯列主元素消去法是由高斯消去法改进的算法 下面浅浅分享一下本人对该方法的理解 Ax b 先说高斯消去法 感觉基本的思路就跟我们手算非齐次线性方程组差不多 在线性代数中 我们求解方程组都是这种思路 消元的过程相当于是 由系数矩阵A和非齐次项
  • linux下代码分析工具Splint

    1 C代码静态分析工具 Its4 读取一个或多个 C C 源程序 将每个源程序分割成函数标志流 然后检查生成的标志是否存在于漏洞数据库中 从而得到每个源程序的所有错误警告列表 并带有相关的描 述 其规则库vulns i4d定义了各种函数的危
  • 【医学图像分割】 MIXED Transformer 、DS-TransUNet、Swin-Unet

  • Qt开发北斗定位系统融合百度地图API及Qt程序打包发布

    Qt开发北斗定位系统融合百度地图API及Qt程序打包发布 1 上位机介绍 最近有个接了一个小型项目 内容很简单 就是解析北斗GPS的串口数据然后输出经纬度 但接过来觉得太简单 就发挥了主观能动性 增加了百度地图API 不但能实时定位 还能在
  • 波兰表达式 & 逆波兰表达式

    1 概述 1 1 什么是波兰表达式 先来看看维基百科对于波兰表达式和逆波兰表单的解释 波兰表示法 Polish notation 或波兰记法 是一种逻辑 算术和代数表示方法 其特点是操作符置于操作数的前面 因此也称做前缀表示法 如果操作符的
  • C++ 大话设计之《观察者模式》(优缺点,设计原理,常用场景)

    观察者模式是一种行为型模式 优点 松散耦合 观察者模式提供了一种松散耦合的设计 使得当一个对象的状态发生变化时 它不需要知道其他对象是如何使用这些信息的 这使得系统更容易扩展和维护 动态关联 观察者模式允许在运行时动态地添加或删除观察者 而