C++观察者模式代码实例

文章目录

    • C++观察者模式代码实例一
    • C++观察者模式代码实例二

C++观察者模式代码实例一

下面是一个简单的C++观察者模式的实现示例,这里仅给出核心代码框架,完整的工程应包含对应的头文件声明及必要的#include指令等。

// 观察者接口(Observer)
class IObserver {
public:virtual ~IObserver() {}virtual void update(const std::string& message) = 0; // 更新方法
};// 主题接口(Subject)
class ISubject {
public:virtual ~ISubject() {}virtual void registerObserver(IObserver* observer) = 0; // 注册观察者virtual void removeObserver(IObserver* observer) = 0; // 移除观察者virtual void notifyObservers(const std::string& message) = 0; // 通知观察者
};// 具体主题(ConcreteSubject)
class ConcreteSubject : public ISubject {
private:std::vector<IObserver*> observers; // 存储观察者列表public:void registerObserver(IObserver* observer) override {observers.push_back(observer);}void removeObserver(IObserver* observer) override {observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());}void notifyObservers(const std::string& message) override {for (const auto& obs : observers) {obs->update(message);}}// 其他业务逻辑,当有状态改变时调用notifyObservers()void changeState(const std::string& newState) {// 假设这里有某种状态变更逻辑std::string message = "状态已更新至:" + newState;notifyObservers(message);}
};// 具体观察者(ConcreteObserver)
class ConcreteObserver : public IObserver {
public:void update(const std::string& message) override {std::cout << "Observer received message: " << message << std::endl;// 在此处响应状态变更,执行观察者的相关操作}
};// 使用示例
int main() {ConcreteSubject subject;ConcreteObserver observer1;ConcreteObserver observer2;subject.registerObserver(&observer1);subject.registerObserver(&observer2);subject.changeState("New State"); // 当状态变化时,所有观察者都会被通知return 0;
}

在这个例子中,ConcreteSubject 是具体的主题类,它可以添加和移除观察者,并在状态变化时通过调用 notifyObservers() 方法通知所有的观察者。ConcreteObserver 类则是实现了 IObserver 接口的观察者,当收到 update() 调用时,会执行相应的更新操作。主程序中创建了一个主题实例和两个观察者实例,并将观察者注册到主题上,当主题状态发生变化时,观察者接收到通知并作出反应。

在实际应用中,观察者模式通常用于设计事件驱动的系统,或者是当对象的状态变化需要自动通知其他对象时。以下是对上述代码实例的进一步阐述:

  1. 应用场景举例:假设你正在构建一个气象站系统,其中ConcreteSubject代表气象站,它记录并报告实时天气数据。ConcreteObserver可以代表各种订阅气象信息的实体,如天气预报网站、农业自动化系统、交通管理系统等。

  2. 主体(Subject):当气象站检测到天气数据发生改变时,例如温度、湿度或风速变化,它会调用notifyObservers()方法,通知所有已注册的观察者。

  3. 观察者(Observer):每一个观察者在接收到update()调用时,会按照自己的需求处理这个更新消息。比如,天气预报网站会在页面上实时更新数据,农业自动化系统会据此调整灌溉计划,交通管理系统则可能据此发布道路预警信息。

  4. 灵活性:观察者模式提供了很好的灵活性,因为新增加的观察者只需实现IObserver接口,并通过主题的registerObserver()方法注册自己,就可以开始接收更新通知,而不需要修改原有的主体或其它观察者。

  5. 松耦合:通过观察者模式,主题与观察者之间的耦合度较低,两者之间通过接口进行交互,这有助于简化系统的维护和扩展。

总之,通过这个简单的C++观察者模式实例,我们可以了解到如何构建一个具有动态通知机制的系统,使得当对象状态改变时,它的所有依赖对象都能得到及时的更新。在实际开发中,观察者模式广泛应用于GUI编程、事件处理、游戏开发、分布式系统等多种场景。

C++观察者模式代码实例二

另外,观察者模式还可以结合C++的一些现代特性进行优化,例如使用智能指针来管理观察者生命周期,以避免内存泄漏问题。下面是一个使用std::shared_ptr改进后的观察者列表管理的例子:

#include <iostream>
#include <vector>
#include <memory>// 观察者接口(Observer)
class IObserver {
public:virtual ~IObserver() {}virtual void update(const std::string& message) = 0;
};// 主题接口(Subject)
class ISubject {
public:virtual ~ISubject() {}virtual void attach(std::shared_ptr<IObserver> observer) = 0;virtual void detach(std::shared_ptr<IObserver> observer) = 0;virtual void notifyObservers(const std::string& message) = 0;
};// 具体主题(ConcreteSubject)
class ConcreteSubject : public ISubject {
private:std::vector<std::shared_ptr<IObserver>> observers;public:void attach(std::shared_ptr<IObserver> observer) override {observers.push_back(observer);}void detach(std::shared_ptr<IObserver> observer) override {observers.erase(std::remove(observers.begin(), observers.end(), observer),observers.end());}void notifyObservers(const std::string& message) override {for (const auto& obs : observers) {obs->update(message);}}// 其他业务逻辑...
};// 具体观察者(ConcreteObserver)
class ConcreteObserver : public IObserver {
public:void update(const std::string& message) override {std::cout << "Observer received message: " << message << std::endl;// 在此处响应状态变更,执行观察者的相关操作}
};// 使用示例
int main() {ConcreteSubject subject;auto observer1 = std::make_shared<ConcreteObserver>();auto observer2 = std::make_shared<ConcreteObserver>();subject.attach(observer1);subject.attach(observer2);subject.notifyObservers("New State"); // 当状态变化时,所有观察者都会被通知return 0;
}

在这个改进版中,观察者列表现在存储的是指向观察者的智能指针,这样当观察者不再需要时,可以自动释放其占用的内存,有效防止了内存泄漏。同时,这也使得主题类与观察者之间的关系管理更加安全和可靠。

此外,观察者模式还可以与C++11/14/17的新特性结合起来,以更好地适应现代C++编程实践。例如:

  1. Lambda 表达式:在某些情况下,你可以使用lambda表达式作为临时观察者,这样就不必为一次性任务专门创建一个类。例如:
subject.attach([&](const std::string& message) {std::cout << "Anonymous observer received message: " << message << std::endl;
});subject.notifyObservers("New State");
  1. std::functionstd::bind:如果你需要传递已经存在的函数或成员函数作为观察者,可以使用std::functionstd::bind来包装这些函数。例如,假设你有一个打印日志的全局函数或类成员函数:
void logMessage(const std::string& message) {std::cout << "Log system received message: " << message << std::endl;
}// 全局函数
subject.attach(logMessage);// 成员函数,假设有一个Logger类
class Logger {
public:void log(const std::string& message) {std::cout << "Logger received message: " << message << std::endl;}
};Logger logger;
subject.attach(std::bind(&Logger::log, &logger, std::placeholders::_1));

通过这些现代C++特性的应用,观察者模式变得更加灵活,可以适应更多样化的场景和需求。同时,结合智能指针和其他内存管理工具,观察者模式的实现可以变得更安全、更易于维护。

除此之外,观察者模式还可以与C++17中的std::variantstd::visit配合使用,以处理不同类型的通知消息。例如,当主题拥有多种状态需要向观察者发送时,可以定义一个包含所有可能状态类型的std::variant变量:

#include <variant>enum class WeatherDataType { Temperature, Humidity, WindSpeed };struct WeatherData {WeatherDataType type;double value;
};class ConcreteSubject : public ISubject {// ...void notifyObservers(WeatherData data) override {for (const auto& obs : observers) {obs->update(data);}}
};class AdvancedObserver : public IObserver {
public:void update(const WeatherData& data) override {std::visit(overloaded{[&](const auto& value) {if (data.type == WeatherDataType::Temperature)handleTemperature(value);// 处理其他类型...},}, data.value);}private:void handleTemperature(double temp) {std::cout << "Received temperature update: " << temp << std::endl;}// 处理其他数据类型的方法...
};

在此案例中,WeatherData结构体包含了数据类型和对应的值,观察者可以根据type字段判断所接收数据的具体类型,并通过std::visit调用相应的方法进行处理。

综上所述,观察者模式与现代C++特性相结合,可以构建出更加灵活、类型安全且易于维护的系统,适用于各种复杂的事件驱动和状态变更通知场景。

python推荐学习汇总连接:
50个开发必备的Python经典脚本(1-10)

50个开发必备的Python经典脚本(11-20)

50个开发必备的Python经典脚本(21-30)

50个开发必备的Python经典脚本(31-40)

50个开发必备的Python经典脚本(41-50)
————————————————

​最后我们放松一下眼睛
在这里插入图片描述

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

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

相关文章

【STM32】STM32学习笔记-WDG看门狗(46)

00. 目录 文章目录 00. 目录01. WDG简介02. IWDG概述03. IWDG框图04. IWDG键寄存器05. WWDG简介06. WWDG框图07. WWDG工作特性08. IWDG和WWDG对比09. 预留10. 附录 01. WDG简介 WDG&#xff08;Watchdog&#xff09;看门狗 看门狗可以监控程序的运行状态&#xff0c;当程序因为…

CentOS7如何使用Docker部署Wiki.Js知识库并实现公网远程访问?

文章目录 1. 安装Docker2. 获取Wiki.js镜像3. 本地服务器打开Wiki.js并添加知识库内容4. 实现公网访问Wiki.js5. 固定Wiki.js公网地址 不管是在企业中还是在自己的个人知识整理上&#xff0c;我们都需要通过某种方式来有条理的组织相应的知识架构&#xff0c;那么一个好的知识整…

tcpdump 常用用法

简要记录下tcpdump用法 监控某个ip上的某个端口的流量 tcpdump -i enp0s25 tcp port 5432 -nn -S 各个参数作用 -i enp0s25 指定抓包的网卡是enp0s3 -nn 显示ip地址和数字端口 &#xff0c;如果只 -n 则显示ip&#xff0c;但是端口为services文件中的服务名 如果一个n…

HTTP状态码合集

目录 1、HTTP状态码 2、状态码的分类 3、常用的状态码 4、总结 1、HTTP状态码 当服务端返回 HTTP 响应时&#xff0c;会带有一个状态码&#xff0c;用于表示特定的请求结果。比如 HTTP/1.1 200 OK&#xff0c;里面的 HTTP/1.1 表示协议版本&#xff0c;200 则是状态码&…

二叉搜索树题目:把二叉搜索树转换为累加树

文章目录 题目标题和出处难度题目描述要求示例数据范围 前言解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 解法三思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;把二叉搜索树转换为累加树 出处&#xff1a;538. 把二叉搜索树转换为累加树 …

【北京迅为】《iTOP-3588开发板网络环境配置手册》第1章 网络基础知识学习

RK3588是一款低功耗、高性能的处理器&#xff0c;适用于基于arm的PC和Edge计算设备、个人移动互联网设备等数字多媒体应用&#xff0c;RK3588支持8K视频编解码&#xff0c;内置GPU可以完全兼容OpenGLES 1.1、2.0和3.2。RK3588引入了新一代完全基于硬件的最大4800万像素ISP&…

vue前端使用get方式获取api接口数据 亲测

// GET请求示例 axios.get(‘http://127.0.0.1:5005/ReadIDCardInfo’) // 将URL替换为真正的API接口地址 .then(response > { if(response.data.code1){ var jsonDataresponse.data.data; console.log(jsonData); // 输出从API接口返回的数据 } }) .catch(error > { con…

windows IIS 申请和配置https(SSL)的工具 win-acme

win-acme 是一个为Windows平台设计的工具&#xff0c;用于从Lets Encrypt自动获取和续期SSL/TLS证书&#xff0c;特别适合用于IIS&#xff08;Internet Information Services&#xff09;服务器。它的使用相对简单&#xff0c;提供了一个用户友好的命令行界面&#xff0c;以及一…

是谁家的小千金跑出来了?

古典的山树绣花设计 精致典雅&#xff0c;上身立体又轻盈 做了粉绿两色&#xff0c;很适合春天的氛围 春天是个适合外出游玩的季节 穿上这件出游真的超美&#xff0c;日常穿也可 超出片很吸睛&#xff01;

推荐一款ssh工具 xshell替代品 electerm

下载地址 electerm&#xff1a; https://electerm.github.io/electerm/ windows版本 产品优势 复制粘贴&#xff0c;可以直接使用ctrlc/v 非常的方便 而且不想xshell 需要账号登陆&#xff0c;有更新弹窗&#xff0c;自身集成了sftp 界面设计更新&#xff0c;比MobaXterm的…

Qt6.8 GRPC功能使用(1)标准GRPC C++ exmple编译环境搭建

MSYS2 环境搭建 1. MSYS2 安装 https://www.msys2.org/#installation 网页中找到Installation&#xff0c; 提供下载&#xff0c; 本次下载版本是 [msys2-x86_64-20240113.exe](https://github.com/msys2/msys2-installer/releases/download/2024-01-13/msys2-x86_64-202401…

批量剪辑利器:轻松调整视频画面尺寸,打造专业级视听体验!

在数字时代&#xff0c;视频已成为我们生活中不可或缺的一部分。无论是制作个人Vlog、企业宣传片&#xff0c;还是进行专业的影视剪辑&#xff0c;调整视频画面的高度和宽度都是至关重要的一步。然而&#xff0c;面对大量视频文件&#xff0c;如何快速、高效地调整画面尺寸呢&a…