C++中的观察者模式:通俗易懂的讲解与实现

server/2024/11/19 11:38:49/

什么是观察者模式

观察者模式是一种常见的设计模式,它解决了这样一个问题:当某个对象的状态发生变化时,如何通知依赖它的其他对象?

用通俗的话说,观察者模式就像我们日常的“订阅-通知”机制:

  • 主题(Subject) 是信息的提供者(比如新闻网站、天气站)。
  • 观察者(Observer) 是信息的订阅者(比如读者、天气App)。
  • 当主题有了新的变化(如新闻更新、天气变化),会通知所有订阅的观察者。

观察者模式的特点

  1. 松耦合
    主题和观察者之间通过接口交互,彼此不直接依赖,可以独立扩展。

  2. 动态订阅与取消订阅
    观察者可以随时订阅或取消订阅,运行时非常灵活。

  3. 通知机制自动化
    主题变化后,会统一通知所有订阅者。


适用场景

  1. 消息通知
    比如新闻推送系统,用户订阅后,新闻更新会自动推送。

  2. 数据驱动更新
    在界面设计中,数据变化时需要动态更新UI(如MVC架构)。

  3. 事件触发系统
    游戏中玩家状态变化需要通知其他玩家,或者股票系统推送实时行情。


C++实现观察者模式:天气预报案例

为了演示观察者模式,我们用一个天气预报系统来举例:

  • 主题(WeatherStation): 模拟一个天气站,用于监控和更新天气。
  • 观察者(WeatherApp): 模拟订阅天气的手机App,接收天气通知。

完整代码

#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
#include <string>// 抽象观察者接口
class WeatherObserver {
public:virtual void updateWeather(const std::string& weather) = 0; // 收到天气更新通知的方法virtual ~WeatherObserver() = default;
};// 抽象主题类(天气站)
class WeatherStation {
private:std::vector<std::shared_ptr<WeatherObserver>> observers; // 保存订阅者列表std::string currentWeather; // 当前天气public:// 添加观察者(订阅)void addObserver(std::shared_ptr<WeatherObserver> observer) {observers.push_back(observer);}// 移除观察者(取消订阅)void removeObserver(std::shared_ptr<WeatherObserver> observer) {observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());}// 通知所有观察者void notifyObservers() {for (const auto& observer : observers) {observer->updateWeather(currentWeather);}}// 更新天气并通知观察者void updateWeather(const std::string& weather) {currentWeather = weather;notifyObservers(); // 通知所有观察者天气变化}
};// 具体观察者类(手机App)
class WeatherApp : public WeatherObserver {
private:std::string appName; // App的名字public:explicit WeatherApp(const std::string& name) : appName(name) {}// 实现天气更新通知方法void updateWeather(const std::string& weather) override {std::cout << appName << " 收到了最新天气:" << weather << std::endl;}
};// 主函数:测试观察者模式
int main() {// 创建天气站(主题)std::shared_ptr<WeatherStation> station = std::make_shared<WeatherStation>();// 创建两个观察者(手机App)std::shared_ptr<WeatherObserver> app1 = std::make_shared<WeatherApp>("天气宝App");std::shared_ptr<WeatherObserver> app2 = std::make_shared<WeatherApp>("气象通App");// 两个App订阅天气站station->addObserver(app1);station->addObserver(app2);// 更新天气,触发通知station->updateWeather("晴天");station->updateWeather("下雨");// 取消天气宝App的订阅station->removeObserver(app1);// 再次更新天气,验证通知station->updateWeather("大风");return 0;
}

代码拆解与分析

  1. 抽象观察者接口(WeatherObserver

    • 定义了一个虚函数 updateWeather(),所有观察者类都必须实现这个方法,用来接收通知。
  2. 主题类(WeatherStation

    • 保存了一个观察者列表(std::vector),用于管理所有订阅者。
    • 提供了 addObserver()removeObserver() 方法,方便动态添加或移除观察者。
    • 通过 notifyObservers() 方法通知所有观察者。
  3. 具体观察者(WeatherApp

    • 每个观察者都实现了 updateWeather() 方法,用来处理天气变化的通知。
  4. 运行逻辑

    • 创建主题和观察者。
    • 观察者订阅主题。
    • 当主题状态改变时,所有观察者都会收到更新通知。

程序运行结果

运行程序后输出如下:

天气宝App 收到了最新天气:晴天
气象通App 收到了最新天气:晴天
天气宝App 收到了最新天气:下雨
气象通App 收到了最新天气:下雨
气象通App 收到了最新天气:大风

可以看到:

  • 两个App订阅后,天气更新时都会收到通知。
  • 取消天气宝App的订阅后,只有气象通App收到通知。

优缺点

优点
  1. 松耦合设计
    • 主题和观察者通过接口交互,方便扩展和维护。
  2. 动态订阅机制
    • 可随时添加或移除观察者。
  3. 统一通知
    • 通知逻辑集中管理,简单直观。
缺点
  1. 性能开销
    • 如果观察者过多,通知过程可能带来性能问题。
  2. 依赖复杂
    • 观察者之间可能产生隐式依赖关系,增加调试难度。

应用场景

  1. 消息推送系统
    比如新闻网站向订阅用户推送最新动态。

  2. 实时数据更新
    数据变化时需要更新多个UI组件。

  3. 事件监听机制
    游戏中角色状态改变时通知其他玩家或系统。


总结

观察者模式是一个简单却功能强大的模式,它通过“发布-订阅”机制解耦了对象之间的依赖,使得代码更加灵活和易维护。在C++中,我们可以通过抽象接口和容器来实现观察者模式,并根据需求灵活扩展。

通过本文的天气预报示例,相信你已经掌握了观察者模式的核心概念及其实现方法!


http://www.ppmy.cn/server/143170.html

相关文章

【青牛科技】汽车收音机调频中频放大器——D1145

性能优势 内置多种电路&#xff1a;内置芯片中频计数缓冲电路及 ETR 微处理控制开关电路&#xff0c;这些电路的集成有助于提升整体性能和功能的集成度&#xff0c;减少外部电路的复杂性和成本1.线性输出信号好&#xff1a;能够输出质量较高的线性信号&#xff0c;这对于保证收…

为什么VScode不能连服务器,MobaXterm可以连

VSCode无法连接服务器但MobaXterm可以连接的原因可能有以下几种‌&#xff1a; ‌SSH协议问题‌&#xff1a;首先检查SSH协议是否正常工作。可以尝试使用其他终端工具&#xff08;如Xshell或MobaXterm&#xff09;连接服务器&#xff0c;如果这些工具也无法连接&#xff0c;说…

2022数学分析【南昌大学】

2022 数学分析 利用极限定义证明: lim ⁡ n → ∞ 4 n 3 + n − 2 2 n 3 − 10 = 2 \mathop {\lim }\limits_{n \to \infty } \frac{{4{n^3} + n - 2}}{{2{n^3} - 10}} = 2 n→∞lim​2n3−104n3+n−2​=2 ∀ ε > 0 \forall \varepsilon>0 ∀ε>0 要使不等式成立,…

基于Python的招聘信息推荐系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

无人机的动力系统节能——CKESC电调小课堂12

1.优化电机和螺旋桨配置 精准匹配&#xff1a;根据无人机的设计用途和负载要求&#xff0c;精确选择电机和螺旋桨。确保电机的功率、扭矩等参数与螺旋桨的尺寸、螺距等完美匹配。例如&#xff0c;对于轻型航拍无人机&#xff0c;选用功率合适的小尺寸电机搭配高效的小螺旋桨&a…

图像重建之深度学习重建

图像重建是计算机视觉领域的一个重要任务。深度学习在图像重建中具有很强的能力和广泛的应用。下面介绍一种常见的深度学习图像重建方法&#xff1a;基于生成对抗网络&#xff08;Generative Adversarial Networks&#xff0c;GANs&#xff09;的图像重建。 基于 GAN 的图像重…

element-plus如何修改内部样式而不影响vue其他组件的样式

使用scoped样式 可以在组件的样式中使用scoped修饰符&#xff0c;以限制样式仅作用于当前组件中的元素。这样就可以在不影响全局样式的情况下&#xff0c;修改element-plus组件的样式。 <template><div class"my-component"><el-button>按钮</e…

基于AOA算术优化的KNN数据聚类算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于AOA算术优化的KNN数据聚类算法matlab仿真。通过AOA优化算法&#xff0c;搜索最优的几个特征数据&#xff0c;进行KNN聚类&#xff0c;同时对比不同个数特征下…