书中是让设计一个气象观测值,持续进行观测。有相应的布告板(显示器)显示不同的气象信息,并且气象站数据更新时,布告板进行相应的信息更新。所谓的观察者模式就是定义了对象之间的一对多关系,当一个对象改变时,他的所有依赖者都会受到通知并自动更新,在本文中以对应一个主题,即气象站,多个对象就作为观察者即为多个布告板。
observer.h定义了两个基类做为主题subject和观察者observer的接口,并且将气象数据放在一个结构体里面。
#ifndef OBSERVER_H_
#define OBSERVER_H_
class observer;
struct data_weather{
float temperature;
float humidity;
float pressure;
};
class subject{
public:
subject(){
}
virtual ~subject(){
}
virtual void Notify(){
}
virtual void Attach(observer*){
}
virtual void Detach(observer*){
}
virtual data_weather GetState(){
return status;
}
virtual void SetState(data_weather &state){
}
private:
data_weather status;
};
class observer{
public:
observer(){
}
~observer(){
}
virtual void update(subject*){
}
};
#endif
weatherdata.h这是实例化的一个气象站主题,对基类中的接口进行实现。
#ifndef WEATHERDATA_H_
#define WEATHERDATA_H_
#include<vector>
#include<iostream>
#include"observer.h"
class weatherdata :public subject{
public:
weatherdata(){
}
~weatherdata(){
}
void Notify();
void Attach(observer*);
void Detach(observer*);
data_weather GetState();
void SetState(data_weather &state);
private:
std::vector<observer*> all_obser;
data_weather status;
};
#endif
weatherdata.cpp
#include"weatherdata.h"
void weatherdata::Attach(observer* pobserver)//添加一个观察者
{
all_obser.push_back(pobserver);
std::cout << "Add an Observer!" << std::endl;
}
void weatherdata::Detach(observer* pobserver)//删除一个观察者
{
std::vector<observer*> ::iterator ptr;
ptr = find(all_obser.begin(),all_obser.end(),pobserver);
if (all_obser.end() != ptr)
{
all_obser.erase(ptr);
std::cout << "Delete an Observer" << std::endl;
}
else
return;
}
void weatherdata::Notify()//通知观察者状态更新
{
std::vector<observer*>::iterator iter = this->all_obser.begin();
for (; iter != all_obser.end(); iter++)
{
(*iter)->update(this);
}
}
data_weather weatherdata::GetState()
{
return this->status;
}
void weatherdata::SetState(data_weather &data)
{
this->status = data;
}
allobserver.h是实例化的观察者,即多个布告板
#ifndef ALLOBSERVER_H_
#define ALLOBSERVER_H_
#include<iostream>
#include"observer.h"
#include"weatherdata.h"
class currentdisplay :public observer{
public:
currentdisplay(){
}
~currentdisplay(){
}
void update(subject*psubject);
void display();
private:
data_weather current_data;
};
class statisticsdisplay :public observer{
public:
statisticsdisplay(){
}
~statisticsdisplay(){
}
void update(subject*psubject){
};
void diplay(){
};
};
//
//class forcastdisplay :public observer{
// void update();
// void diplay();
//};
#endif
allobserver.cpp
#include"allobserver.h"
void currentdisplay::update(subject*psubject)
{
this->current_data = psubject->GetState();
display();
}
void currentdisplay::display()
{
std::cout << "Current condition: " << current_data.temperature << "F degrees and "
<< current_data.humidity << "% humidity" << std::endl;
}
主函数main.cpp
#include<iostream>
#include"observer.h"
#include"allobserver.h"
#include"weatherdata.h"
int main()
{
observer* p1 = new currentdisplay();
subject* pSubject = new weatherdata();
observer* p2 = new statisticsdisplay();
pSubject->Attach(p1);
pSubject->Attach(p2);
data_weather old_data = { 80, 65, 30.4f };
pSubject->SetState(old_data);
pSubject->Notify();
std::cout << "-------------------------------------" << std::endl;
pSubject->Detach(p2);
data_weather new_data = { 82, 70, 29.2f };
pSubject->SetState(new_data);
pSubject->Notify();
return 0;
}
运行结果
这种模式可以使主题和观察者之间松耦合。当有新类型的观察者出现时,主题的代码不需要修改,主题只会发送通知给所有实现了观察者接口的对象。并且我们可以独立的复用主题或观察者,因为两者是松耦合,并且改变两者中的一方,并不会影响另一方。所以松耦合设计也是软件设计的一个原则,可以建立弹性的面向对象系统,灵活应对变化。