【C++设计模式之观察者模式:行为型】分析及示例

简介

观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,使得当一个对象的状态发生变化时,所有依赖它的对象都能够自动收到通知并更新。

描述

观察者模式由两个核心件组成:主题(Subject)和观察者(Observer)。主题是一个可被观察的对象,它维护了一个观察者列表,可以动态地添加、删除和通知观察者。观察者是依赖于主题的对象,当主题发生变化时,观察者会自动更新自己的状态。

原理

观察者模式通过定义了主题和观察者之间的接口,使得主题和观察者可以彼此独立地进行交互。当主题的状态发生变化时,它会通知所有的观察者,而观察者会根据主题的通知进行相应的更新。

类图

在这里插入图片描述

Subject:目标类,它是一个抽象类,也是所有目标对象的父类。它用一个列表记录当前目标对象有哪些观察者对象,并提供增加、删除观察者对象和通知观察者对象的接口。
Observer:观察者类,它也是一个抽象类,是所有观察者对象的父类;它为所有的观察者对象都定义了一个名为update的方法(也叫成员函数)。当目标对象的状态改变时,它就是通过调用它的所有观察者对象的update方法来通知它们的。
ConcreteSubject:具体目标类,可以有多个不同的具体目标类,它们同时继承Subject类。一个目标对象就是某个具体目标类的对象,一个具体目标类负责定义它自身的事务逻辑,并在状态改变时通知它的所有观察者对象。
ConcreteObserver:具体观察者类,可以有多个不同的具体观察者类,它们同时继承Observer类。一个观察者对象就是某个具体观察者类的对象。每个具体观察者类都要重定义Observer类中定义的update方法,在该方法中实现它自己的任务逻辑,当它被通知的时候(目标对象调用它的update方法)就执行自己特有的任务。

示例

假设有一个天气预报系统,其中天气数据是主题,用户界面、手机App电视等是观察者。当天气数据更新时,所有的观察者都能够收到通知并更新自己的内容。

C++示例代码如下:

#include <iostream>
#include <vector>// 主题接口
class Subject {
public:virtual void attach(Observer* observer) = 0;virtual void detach(Observer* observer) = 0;virtual void notify() = 0;
};// 观察者接口
class Observer {
public:virtual void update(const std::string& message) = 0;
};// 具体主题
class WeatherData : public Subject {
public:void attach(Observer* observer) override {observers.push_back(observer);}void detach(Observer* observer) override {for (auto it = observers.begin(); it != observers.end(); ++it) {if (*it == observer) {observers.erase(it);break;}}}void notify() override {for (Observer* observer : observers) {observer->update(message);}}void setMessage(const std::string& message) {this->message = message;notify();}private:std::vector<Observer*> observers;std::string message;
};// 具体观察者
class UserInterface : public Observer {
public:void update(const std::string& message override {std::cout << "User Interface: " << message << std::endl;}
};class MobileApp : public Observer {
public:void update(const std::string& message) override {std::cout << "Mobile App: " << message << std::endl;}
};class TV : public Observer {
public:void update(const std::string& message) override {std::cout << "TV: " << message << std::endl;}
};// 使用示例
int main() {WeatherData weatherData;UserInterface userInterface;MobileApp mobileApp;TV tv;weatherData.attach(&userInterface);weatherData.attach(&mobileApp);weatherData.attach(&tv);weatherData.setMessage("The is sunny.");weatherData.detach(&mobileApp);weatherData.setMessage("The weather is rainy");return 0;
}

输出结果

User Interface: The weather is sunny.
Mobile App: The weather is sunny.
TV: The is sunny.
User Interface: The weather is rainy.
TV: The weather is rainy.

解释

在上述示例中,主题接口(Subject)定义了操作观察者的方法,包括添加观察者、删除观察者和通知观察者。
具体主题(WeatherData)实现了主题接口,并维护了一个观察者列表。
观察者接口(Observer)定义了观察者的更新方法,具体观察者(UserInterface、MobileApp、TV)实现了观察者接口,并根据主题的通知进行相应的更新。

在示例中,创建了一个天气数据对象(WeatherData)作为主题,然后创建了三个观察者(UserInterface、MobileApp、TV)。将观察者添加到天气数据对象的观察者列表中,然后模拟天气数据发生变化,通过调用主题的notify方法通知所有的观察者。察者接收到通知后,会调用自己的update方法进行相应的更新操作。

结论

结论观察者模式通过定义了一种一对多的依赖关系,使得主题和观察者之间能够彼此独立地进行交互。它实现了对象间的解耦,当一个对象的状态发生变化时,所有依赖它的对象都能够自动收到通知并进行相的更新。

观察者模式适用场景:

  • 当一个对象的改变需要同时通知其他对象,并且不道具体有多少个对象需要通知时,可以使用观察者模式实现松散的耦合。
  • 当一个对象需要将自己的改变通知给其他对象,但是又希望避免耦合时,可以使用观察者模式。

观察者模式常见的应用场景包括事件驱动系统、GUI界面组件、消息队列系统等。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mind Map:大语言模型中的知识图谱提示激发思维图10.1+10.2+10.7

知识图谱提示激发思维图 摘要介绍相关工作方法第一步&#xff1a;证据图挖掘第二步&#xff1a;证据图聚合第三步&#xff1a;LLM Mind Map推理 实验实验设置医学问答长对话问题使用KG的部分知识生成深入分析 总结 摘要 LLM通常在吸收新知识的能力、generation of hallucinati…

第二证券:突发!A股T+0?刚刚,紧急回应!

沪深生意所急迫回应 6日&#xff0c;商场传出一个消息&#xff0c;传延伸A股生意时刻和部分票可日内T0一次。一个版本是提早至9点&#xff0c;然后下午延伸至15&#xff1a;30&#xff0c;另一个版本是上午推延至12点&#xff0c;下午延伸至16&#xff1a;00。 7日&#xff0…

漏刻有时物联网刷脸支付可视化大屏(柱图、支付统计、数字滚动插件numberAnimate.js、jquery.liMarquee.js插件、横向滚动字幕代码)

numberAnimate.js插件的使用 numberAnimate.js 是一个用于在网页上创建动画数字效果的 JavaScript 插件。它可以帮助开发者轻松实现数字的渐变、过渡、闪烁等动画效果。 以下是 numberAnimate.js 的主要特点&#xff1a; 多样化的动画效果&#xff1a;numberAnimate.js 提供…

【visual studio 小技巧】项目属性->生成->事件

需求 我们有时会用到一些dll&#xff0c;需要把这些dll和我们生成的exe放到一起&#xff0c;一般我们是手动自己copy&#xff0c; 这样发布的时候&#xff0c;有时会忘记拷贝这个dll&#xff0c;导致程序运行出错。学会这个小技巧&#xff0c;就能实现自动copy&#xff0c;非…

12P2532X162-233A KJ3222X1-BA1 CE4003S2B3 EMERSON CONTROLLER

12P2532X162-233A KJ3222X1-BA1 CE4003S2B3 EMERSON CONTROLLER EDGEBoost I/O模块是一种可扩展的模块化解决方案&#xff0c;集成到Premio的工业计算机中&#xff0c;通过即插即用的可扩展性提供增强的可靠性。这些附加模块有助于解决在加固边缘出现的设计限制和兼容性问题。…

HRB系列 电源升压模块直流可调低压升高压输出DC/DC升压变换器

特点 效率高达 80%以上1*2英寸标准封装单电压输出价格低稳压输出工作温度: -40℃~85℃阻燃封装&#xff0c;满足UL94-V0 要求温度特性好可直接焊在PCB 上 应用 HRB W2~40W 系列模块电源是一种DC-DC升压变换器。该模块电源的输入电压分为&#xff1a;4.5~9V、9~18V、及18~36V、…

大厂秋招真题【BFS+DP】华为20230921秋招T3-PCB印刷电路板布线(留学生专场)

华为20230921秋招T3-PCB印刷电路板布线&#xff08;留学生专场&#xff09; 题目描述与示例 题目描述 在PCB印刷电路板设计中&#xff0c;器件之间的连线&#xff0c;要避免线路的阻抗值增大&#xff0c;而且器件之间还有别的器任和别的干扰源&#xff0c;在布线时我们希望受…

Vue中如何进行数据可视化雷达图展示

在Vue中进行数据可视化雷达图展示 数据可视化是将数据以图形方式呈现的过程&#xff0c;雷达图是其中一种常用的图表类型&#xff0c;用于可视化多个维度的数据。Vue.js作为一个流行的JavaScript框架&#xff0c;提供了许多工具和库来实现数据可视化。本文将介绍如何使用Vue来…

SpringBoot文件上传

前端 <form action"/upload" method"post" enctype"multipart/form-data">姓名: <input type"text" name"username"><br>年龄: <input type"text" name"age"><br>头像:…

【应用层协议】初始Http,fiddler的使用

文章目录 1. HTTP概念2. 下载fiddler及使用获得HTTP协议格式2.1 fiddler的下载2.2 fiddler使用 3. HTTP请求&#xff08;Request&#xff09;3.1 请求行3.1.1 URL3.1.2 方法3.1.2.1 GET3.1.2.2 POST3.1.2.3 其他方法 3.2 报头&#xff08;header&#xff09;3.3 空白行3.4 正文…

CentOS Stream9 安装远程桌面服务 Xrdp

1. 安装 XRDP 若服务器本身没有桌面则首先需要安装本地桌面&#xff1a; yum -y groups install "GNOME Desktop" startx配置源&#xff1a; dnf install epel-release安装 xrdp dnf install xrdp 2. 配置 Xrdp Xrdp 配置文件位于 /etc/xrdp 目录中。对于常规 X…

网络安全总结

前言 本文内容主要摘抄网络规划设计师的教材和腾讯-SUMMER课堂&#xff0c;主要对网络安全进行简单梳理和总结 OSI安全体系 X轴表示8种安全机制&#xff0c;Y轴表示OSI7层模型&#xff0c;Z轴表示5种安全服务&#xff0c;图中X是水平&#xff0c;Y轴竖直&#xff0c;Z轴向外…