当前位置: 首页 > ai >正文

【C++设计模式之Observer观察者模式】

Observer观察者模式

  • 模式定义
  • 动机(Motivation)
  • 结构(Structure)
  • 应用场景一(气象站)实现步骤
    • 1.定义观察者接口
    • 2.定义被观察者(主题)接口
    • 3.实现具体被观察者对象(气象站)
    • 4.实现具体观察者(例如:显示屏)
    • 5.main.cpp中使用示例
    • 6.输出结果
    • 7. 关键点
  • 应用场景二(温度传感器)实现步骤
    • 1.定义观察者接口
    • 2.定义被观察者接口
    • 3.实现具体被观察者(温度传感器)
    • 4.实现具体观察者(温度显示屏)
    • 5.使用示例
  • 要点总结


模式定义

观察者模式:定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。

允许对象(观察者)订阅另一个对象(被观察者)的状态变化,并在状态变化时自动接收通知。

动机(Motivation)

  • 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”——一个对象(目标对象)的状态发送改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于密切,将使软件不能很好地抵御变化。
  • 使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。

结构(Structure)

在这里插入图片描述

应用场景一(气象站)实现步骤

1.定义观察者接口

observer.h头文件

#pragma once
#include<vector>
#include<algorithm>//观察者接口
class Observer {
public:virtual ~Observer() = default;virtual void update() = 0;     //更新方法(纯虚函数)
};

2.定义被观察者(主题)接口

subject.h头文件

#pragma once
#include "observer.h"class Subject {
public:virtual ~Subject() = default;virtual void attach(Observer*observer) = 0;   //注册观察者virtual void detach(Observer*observer) = 0;   //移除观察者virtual void notify() = 0;                    //通知观察者protected:std::vector<Observer*> observers_;             //存储观察则列表
};

3.实现具体被观察者对象(气象站)

concretesubject.h

#pragma once
#include"subject.h"class WeatherStation :public Subject {
public://注册观察者void attach(Observer* observer)override {observers_.push_back(observer);}//移除观察者void detach(Observer*observer)override {auto it = std::remove(observers_.begin(), observers_.end(), observer);observers_.erase(it, observers_.end());}//通知所有观察者void notify()override {for (auto observer : observers_) {observer->update();}}//更新气象数据并触发通知void setMeasurements(float temperature, float humidity) {temperature_ = temperature;humidity_ = humidity;notify();    //数据变化时通知观察者}//获取数据(供观察者拉取)float getTemperature()const { return temperature_; }float getHumidity()const { return humidity_; }private:float temperature_ = 0.0f;float humidity_ = 0.0f;
};

4.实现具体观察者(例如:显示屏)

concreteobserver.h

#pragma once
#include<iostream>
#include"observer.h"
#include"concretesubject.h"
class Display :public Observer {
public:explicit Display(WeatherStation&station):station_(station){}//当被观察者通知时,更新显示void update()override {std::cout << "Temperature: " << station_.getTemperature()<< " ℃,Humidity : " << station_.getHumidity() << "% \n";}
private:WeatherStation& station_;
};

5.main.cpp中使用示例

#include <iostream>
#include"concretesubject.h"
#include"concreteobserver.h"int main()
{WeatherStation station;  // 被观察者(气象站)Display display1(station);  // 观察者1(显示屏)Display display2(station);  // 观察者2// 注册观察者station.attach(&display1);station.attach(&display2);// 更新数据,自动触发观察者更新station.setMeasurements(25.5f, 60.0f);station.setMeasurements(26.0f, 55.0f);// 移除一个观察者station.detach(&display2);station.setMeasurements(27.0f, 50.0f);return 0;
}

6.输出结果

Temperature: 25.5 ℃,Humidity : 60%
Temperature: 25.5 ℃,Humidity : 60%
Temperature: 26 ℃,Humidity : 55%
Temperature: 26 ℃,Humidity : 55%
Temperature: 27 ℃,Humidity : 50%

7. 关键点

  • 松耦合:观察者和被观察者通过接口交互,无需知道彼此的具体实现。

  • 推拉模型

    • 推模式:被观察者将数据直接推送给观察者(通过 update 方法参数)。

    • 拉模式:观察者主动从被观察者拉取数据(本例中使用 getTemperature() 和 getHumidity())。

  • 内存管理:需确保观察者的生命周期覆盖被观察者,或使用 shared_ptr 管理资源。

应用场景二(温度传感器)实现步骤

1.定义观察者接口

observer.h

#pragma once
//定义观察者接口
class Observer {
public:virtual ~Observer() = default;virtual void update() = 0;    //更新方法
};

2.定义被观察者接口

subject.h

#pragma once
#include"observer.h"
#include<vector>
class Subject {
public:virtual ~Subject() = default;virtual void attach(Observer*observer) = 0;  //注册观察者virtual void detach(Observer*observer) = 0;  //移除观察者virtual void notify() = 0;                   //通知观察者
protected:std::vector<Observer*>observers_;
};

3.实现具体被观察者(温度传感器)

concretesubject.h

#pragma once
#include"subject.h"
#include <algorithm>class TemperatureSensor :public Subject {
public:void attach(Observer*observer)override {observers_.push_back(observer);}void detach(Observer* observer) override {auto it = std::remove(observers_.begin(), observers_.end(), observer);observers_.erase(it, observers_.end());}void notify() override {for (auto observer : observers_) {observer->update();}}void setTemperature(float temp) {temperature_ = temp;notify();  // 温度变化时通知所有观察者}float getTemperature() const { return temperature_; }private:float temperature_ = 0.0f;
};

4.实现具体观察者(温度显示屏)

concreteobserver.h

#pragma once
#include"observer.h"
#include "concretesubject.h"
#include<iostream>class TemperatureDisplay :public Observer {
public:explicit TemperatureDisplay(TemperatureSensor&sensor):sensor_(sensor){}void update()override {std::cout << "当前温度: " << sensor_.getTemperature() << " ℃\n";}
private:TemperatureSensor& sensor_;
};

5.使用示例

#include"concreteobserver.h"
#include"concretesubject.h"int main() {TemperatureSensor sensor;TemperatureDisplay display(sensor);sensor.attach(&display);sensor.setTemperature(25.5f);  // 输出:当前温度: 25.5°Csensor.detach(&display);sensor.setTemperature(26.0f);  // 无输出return 0;
}

要点总结

  • 使用面向对象的抽象,Observer模式使得我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达致松耦合。
  • 目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。
  • 观察者自己决定是否需要订阅通知,目标对象对此一无所知。
  • Observer模式是基于事件的UI框架中非常常用的设计模式,也是MVC模式的一个重要组成部分。
http://www.xdnf.cn/news/4824.html

相关文章:

  • 5G让媒体传播更快更智能——技术赋能内容新时代
  • 深入详解人工智能数学基础——微积分中的微分方程在神经常微分方程(Neural ODE)中的应用
  • Vue3+ts复制图片到剪贴板
  • git相关
  • TB6600HG-富利威
  • k8s之statefulset
  • 养生:塑造健康生活的良方
  • 信赖域策略优化TRPO算法详解:python从零实现
  • Unity3D实现Render Streaming推送视频流的解决方案
  • Python爬虫(22)Python爬虫进阶:Scrapy框架动态页面爬取与高效数据管道设计
  • matlab转python
  • learning ray之ray强化学习/超参调优和数据处理
  • 出一期Source Insigned的使用教程
  • 湖南省密码协会成立,麒麟信安担任副会长单位共话密码创新应用之道
  • python里面的class,类,方法,函数,def
  • 深入剖析 I/O 复用之 select 机制
  • debian12 安装docker
  • ImportError: cannot import name ‘Optional‘ from ‘pydantic‘
  • C++错误: multiple definition of `Q‘
  • 超详细讲解注意力机制、自注意力机制、多头注意力机制、通道注意力机制、空间注意力机制
  • CCF编程能力等级认证 一级 第一次课
  • 【PhysUnits】3 量纲接口实现解析(dimensional.rs)
  • 如何处理oracle 12c DG归档日志缺失(gap)导致备库同步中断问题
  • 创建型模式:抽象工厂(Abstract Factory)模式
  • Matlab 数控车床进给系统的建模与仿真
  • ubuntu24.04安装cuda
  • 微程序控制器的详细工作过程
  • 基于精准光域控制的光触发RFID标签
  • 【万字长文】深入浅出 LlamaIndex 和 LangChain:从RAG到智能体,轻松驾驭LLM应用开发
  • python调用国税乐企直连接口开数电票之API调用工具类