Observer观察者模式
- 模式定义
- 动机(Motivation)
- 结构(Structure)
- 应用场景一(气象站)实现步骤
-
- 1.定义观察者接口
- 2.定义被观察者(主题)接口
- 3.实现具体被观察者对象(气象站)
- 4.实现具体观察者(例如:显示屏)
- 5.main.cpp中使用示例
- 6.输出结果
- [7. 关键点](#7. 关键点)
- 应用场景二(温度传感器)实现步骤
- 要点总结
模式定义
观察者模式:定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。
允许对象(观察者)订阅另一个对象(被观察者)的状态变化,并在状态变化时自动接收通知。
动机(Motivation)
- 在软件构建过程中,我们需要为某些对象建立一种"通知依赖关系"------一个对象(目标对象)的状态发送改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于密切,将使软件不能很好地抵御变化。
- 使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。
结构(Structure)

应用场景一(气象站)实现步骤
1.定义观察者接口
observer.h头文件
cpp
#pragma once
#include<vector>
#include<algorithm>
//观察者接口
class Observer {
public:
virtual ~Observer() = default;
virtual void update() = 0; //更新方法(纯虚函数)
};
2.定义被观察者(主题)接口
subject.h头文件
cpp
#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
cpp
#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
cpp
#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中使用示例
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.输出结果
cpp
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
cpp
#pragma once
//定义观察者接口
class Observer {
public:
virtual ~Observer() = default;
virtual void update() = 0; //更新方法
};
2.定义被观察者接口
subject.h
cpp
#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
cpp
#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
cpp
#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.使用示例
cpp
#include"concreteobserver.h"
#include"concretesubject.h"
int main() {
TemperatureSensor sensor;
TemperatureDisplay display(sensor);
sensor.attach(&display);
sensor.setTemperature(25.5f); // 输出:当前温度: 25.5°C
sensor.detach(&display);
sensor.setTemperature(26.0f); // 无输出
return 0;
}
要点总结
- 使用面向对象的抽象,Observer模式使得我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达致松耦合。
- 目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。
- 观察者自己决定是否需要订阅通知,目标对象对此一无所知。
- Observer模式是基于事件的UI框架中非常常用的设计模式,也是MVC模式的一个重要组成部分。