个人笔记(不一定正确)
C++实现:
#ifndef _WEATHER_H_
#define _WEATHER_H_
#include<iostream>
#include<vector>
using namespace std;
//观察者接口类
class Observer
{
private:
/* data */
public:
Observer(/* args */){}
~Observer(){}
virtual void update(float temperature, float humidity, float pressure) = 0;
};
//主题类, 使用虚函数实现接口功能
class Subject
{
private:
/* data */
public:
Subject(/* args */){}
~Subject(){}
//注册观察者
virtual void registerObserver(Observer* o){}
//移除观察者
virtual void removeObserver(Observer* o){}
//变更通知
virtual void notifyObserver(){}
};
//WeatherData类: 具体的主题类,除了天气主题,也可以自定义其他的主题
class WeatherData:public Subject
{
private:
/* data */
vector<Observer*> observerList; //观察者列表
float temperature;
float humidity;
float pressure;
public:
WeatherData(/* args */){
//这里observerList vector的性质,就不用先初始化了
}
~WeatherData(){}
//已有方法
float getTemperature(){
return this->temperature;
}
float getHumidity(){
return this->humidity;
}
float getPressure(){
return this->pressure;
}
void measurementsChanged(){
// when the value change,this function would be called,we're supported to implement our deal here
notifyObserver();
}
//注册观察者
void registerObserver(Observer* o){
observerList.push_back(o);
}
//移除观察者
void removeObserver(Observer* o){
vector<Observer*>::iterator it;
for(it=observerList.begin();it!=observerList.end();){
if(*it == o){
it = observerList.erase(it); //迭代器erase之后,会导致it++失效,所以这里要做返回值处理
}else{
it ++;
}
}
}
//通知观察者
void notifyObserver(){
vector<Observer*>::iterator it;
for(it=observerList.begin();it!=observerList.end();it++){
Observer* o;
o = *it;
o->update(temperature, humidity, pressure);
}
}
//为了方便测试,我们增加一个set方法
void setMeasurements(float temperature, float humidity, float pressure){
this->temperature = temperature;
this->humidity = humidity;
this->pressure = pressure;
measurementsChanged();
}
// 其他WeatherData方法...
};
/**/
//公告板接口类
class DisplayElement
{
private:
public:
DisplayElement(){}
~DisplayElement(){}
virtual void display() = 0;
};
#endif
#include "weather.hpp"
//具体公告板类:CurrentConditionDisplay
class CurrentConditionDisplay:public Observer, public DisplayElement
{
private:
/* data */
float temperature;
float humidity;
Subject* weatherData;
public:
CurrentConditionDisplay(Subject* weatherData){
this->weatherData = weatherData;
weatherData->registerObserver(this);
}
~CurrentConditionDisplay(){}
//update() 实现
void update(float temperature, float humidity, float pressure){
cout<<"检查变更:"<<endl;
this->temperature = temperature;
this->humidity = humidity;
display();
}
//display() 实现
void display(){
cout<< "CurrentConditionDisplay:"<<endl;
cout << "温度: "<<this->temperature<<endl;
cout << "湿度: "<<this->humidity<<endl;
}
};
//预测公告板类
class ForecastDisplay:public Observer,public DisplayElement
{
private:
float pre_temperature;
float pre_humidity;
float pre_pressure;
Subject* weatherData; //订阅的主题
public:
ForecastDisplay(Subject* weatherData){
this->weatherData = weatherData;
weatherData->registerObserver(this);
}
~ForecastDisplay(){}
//update() 实现
void update(float temperature, float humidity, float pressure){
cout<<"检查变更:"<<endl;
this->pre_temperature = temperature + 1;
this->pre_humidity = humidity +1 ;
this->pre_pressure = pressure -1;
display();
}
//display() 实现
void display(){
cout<< "CurrentConditionDisplay:"<<endl;
cout << "预测温度: "<<this->pre_temperature<<endl;
cout << "预测湿度: "<<this->pre_humidity<<endl;
cout << "预测气压: "<<this->pre_pressure<<endl;
}
};
/* 随时拓展其他的公告板类*/
int main(){
//实例化主题
Subject* wd = new WeatherData(); //也可以直接 WeatherData* wd = new WeatherData();
//注册观察者
// Observer* cw = new CurrentConditionDisplay(wd);
// Observer* pw = new ForecastDisplay(wd);
CurrentConditionDisplay cw(wd);
ForecastDisplay fw(wd);
//weather中心更改值
WeatherData* wd_v2 = (WeatherData*)wd;
wd_v2->setMeasurements(13,20,30);
cout <<endl;
wd_v2->setMeasurements(23,10,10);
//移除观察者测试
wd_v2->removeObserver(&fw);
cout <<endl;
wd_v2->setMeasurements(24,12,10);
//释放对象
if(wd!=NULL){
delete wd;
}
if(wd_v2!=NULL){
delete wd_v2;
}
return 0;
}
*/
output:
检查变更:
CurrentConditionDisplay:
温度: 13
湿度: 20
检查变更:
CurrentConditionDisplay:
预测温度: 14
预测湿度: 21
预测气压: 29
检查变更:
CurrentConditionDisplay:
温度: 23
湿度: 10
检查变更:
CurrentConditionDisplay:
预测温度: 24
预测湿度: 11
预测气压: 9
检查变更:
CurrentConditionDisplay:
温度: 24
湿度: 12
总结:
以上的方法,只实现了观察者模式中的推送模式,观察者们都是被动接受消息的,接下来看看观察者主动拉取信息的模式该怎么实现。