02_观察者模式
定义:
观察者模式定义对象之间的 一对多 依赖,这样一来,当一个对象改变状态时,
它得所有依赖者都会收到通知并自动更新。
设计原则:
尽量做到交互得对象之间得松耦合设计。
松耦合设计:允许我们建造能够应对变化的、有弹性的OO系统,因为对象之间的互相依赖降低到最低。
简述:
这个模式可以让你的对象在发生某些事情时保持消息灵通。
出版者(主题, subject) + 订阅者(观察者, observer) = 观察者模式(一对多)
p.s. 在“01_设计者模式”中,主题数据变化时,对象不会被通知。
main.cpp
/**
* @file main.cpp
* @author JeffyGao (gaojune_better@qq.com)
* @version 0.1
* @date 2022-04-29
* @copyright Copyright (c) 2022
*
* 文件包含:
* Subject.h 主题
* Observer.h 观察者
* DisplayElement.h 数据展示
*/
#include <iostream>
#include "Subject.h"
#include "Observer.h"
#include "DisplayElement.h"
// 测试案例
int main( ){
WeatherData* weatherData = new WeatherData();
CurrentConditionsDisplay* currentConditionsDisplay = new CurrentConditionsDisplay(*weatherData);
weatherData->SetMeasurements( 80, 65, 30.4f );
weatherData->SetMeasurements( 82, 70, 29.8f );
weatherData->SetMeasurements( 78, 90, 39.4f );
return 0;
}
Observer.h
/**
* @file Observer.h
* @author JeffyGao (gaojune_better@qq.com)
* @version 0.1
* @date 2022-04-29
* @copyright Copyright (c) 2022
*
* @brief 观察者(Observer) 接口
* 简介:
* 本文件为 观察者(Observer) 的创建。
* 所有的观察者都实现 Ovserver接口,所以它们都不得不实现 update() 方法。
*
* 文件包含:
* class Observer 观察者
* Update( ) 更新数据
*/
#pragma once
#include <iostream>
#include "Subject.h"
class Observer{
public:
Observer( ){
std::cout << "ctor Observer" << std::endl;
}
~Observer( ){
std::cout << "dtor Observer" << std::endl;
}
public:
// 更新数据。
// 当气象测量数据变化时观察者从 Subject获得的状态值。
void Update( float tmep, float humidity, float pressure ){
std::cout << "func_Update 温度: " << tmep << " 湿度: " << humidity << " 气压:" << pressure << std::endl;
}
};
DisplayElement.h
/**
* @file DisplayElement.h
* @author JeffyGao (gaojune_better@qq.com)
* @version 0.1
* @date 2022-04-29
* @copyright Copyright (c) 2022
*
* @brief 数据显示(DisplayElement) 接口
* 简介:
* 本文件为 数据显示(DisplayElement) 的创建。
* DiaplayElement接口只包含一个方法 Display(),当元素需要显示时,调用此方法。
*
* 文件包含:
* class DiaplayElement 展示数据
* Display( ) 展示数据
* class CurrentConditionsDisplay : public Observer, public DisplayElement
* CurrentConditionsDisplay( ) 用它来把显示注册为观察者
* Update( ) 更新数据
* Display( ) 重写了 virtual DiaplayElement::Display() = 0
*/
#pragma once
#include <iostream>
#include "Subject.h"
#include "Observer.h"
// 前置声明
class Observer;
class DisplayElement{
public:
DisplayElement( ){
std::cout << "ctor DisplayElement" << std::endl;
}
~DisplayElement( ){
std::cout << "dtor DisplayElement" << std::endl;
}
public:
virtual void Display( ) = 0;
};
/**
* 这个显示实现了 Observer接口,所以它可以从 WeatherData对象中获取变化
* 它也实现了 DisplayElement,因为我们的 API 打算要求所有显示元素实现这个接口
*/
class CurrentConditionsDisplay : public Observer, public DisplayElement{
private:
float _temperature;
float _humidity;
WeatherData _weatherData;
public:
// ctor
CurrentConditionsDisplay( ){
std::cout << "CurrentConditionsDisplay ctor" << std::endl;
}
// 构造器被传入 weatherData对象( Subject ),我们用它来把显示注册为观察者
CurrentConditionsDisplay( WeatherData weatherData ){
std::cout << "CurrentConditionsDisplay( WeatherData weatherData ) ctor" << std::endl;
this->_weatherData = weatherData;
weatherData.RegisterObserver( *this );
}
// class Observer 里有定义
void Update( float temperature, float humidity, float pressure ){
this->_temperature = temperature;
this->_humidity = humidity;
Display( );
}
// 重写了 virtual DiaplayElement::Display() = 0
void Display( ){
std::cout << "当前温度: " << _temperature << " 当前湿度: " << _humidity << std::endl;
}
};
Subject.h
/**
* @file Subject.h
* @author JeffyGao (gaojune_better@qq.com)
* @version 0.1
* @date 2022-04-29
* @copyright Copyright (c) 2022
*
* @brief 主题 Subject
* 简介:
* 本文件为 主题(Subject)的创建
*
* 文件包含:
* class Subject 主题
* RegisterObserver( ) 注册 Observer
* RemoveObserver( ) 移除 Observer
* NotifyObservers( ) 当 Subject 的状态改变时,这个方法会被调用,以通知所有的观察者
*
* class WeatherData : public Subject 实现 Subject 接口
* WeatherData( ) 构造 _observer
* RegisterObserver( ) 注册 Observer
* RemoveObserver( ) 移除 Observer
* NotifyObservers( ) 把所有状态都告诉 观察者
* MeasurementsChanged( ) 从气象站得到更新的测量值时,通知 Observer
* SetMeasurements( ) 设置测量值
*/
#pragma once
#include <iostream>
#include <vector>
#include "Observer.h"
class Subject{
public:
Subject( ){
std::cout << "ctor Subject" << std::endl;
}
~Subject( ){
std::cout << "dtor Subject" << std::endl;
}
public:
// 注册 Observer
void RegisterObserver( Observer o );
// 移除 Observer
void RemoveObserver( Observer o );
// 当 Subject 的状态改变时,这个方法会被调用,以通知所有的观察者
void NotifyObservers( );
};
// 实现 Subject 接口
class WeatherData : public Subject{
public:
WeatherData( ){
std::cout << "ctor WeatherData" << std::endl;
_observer = std::vector<Observer>( );
}
~WeatherData( ){
std::cout << "dtor WeatherData" << std::endl;
}
public:
// 注册
void RegisterObserver( Observer o ){
std::cout << "RegisterObserver" << std::endl;
//_observer->add( o );
}
// 移除
void RemoveObserver( Observer o ){
std::cout << "RemoveObserver" << std::endl;
// _observer->remove( o );
}
// 把所有状态都告诉 观察者
// 因为它们都是 Observer,我们知道它们都实现了 update(),所以知道如何通知它们
void NotifyObservers( ){
std::cout << "func NotifyObservers()" << std::endl;
int count_num = 1;
std::cout << "begin NotifyObservers" << std::endl;
// 不理解这里的写法,vector<Observer> 里面的数据代表什么?
// for ( Observer &ob : _observer ){
// std::cout << " No. " << count_num++ << std::endl;
// ob.Update( _temperature, _humidity, _pressure );
// }
_observer[0].Update( _temperature, _humidity, _pressure );
}
// 从气象站得到更新的测量值时,通知 Observer
void MeasurementsChanged( ){
std::cout << "func MeasurementsChanged()" << std::endl;
std::cout << "goto func NotifyObservers()" << std::endl;
NotifyObservers( );
}
// 设置测量值
void SetMeasurements( float temperature, float humidity, float pressure ){
std::cout << "func SetMeasurements()" << std::endl;
this->_temperature = temperature;
this->_humidity = humidity;
this->_pressure = pressure;
// 数据改变了
std::cout << "goto func MeasurementsChanged()" << std::endl;
MeasurementsChanged( );
}
// 其它 WeatherData 的方法可以继续往后面写
private:
std::vector<Observer> _observer;
float _temperature; // 温度
float _humidity; // 湿度
float _pressure; // 气压
};