您的位置:首页 > 编程语言 > C语言/C++

行为模式之观察者模式(Observer Pattern)(C++实现)******

2012-06-28 20:53 615 查看
观察者模式(Observer Pattern)行为模式.
它是应用最多,影响最广的模式之一,因为Observer的一个实例Model/View/Control(MVC)结构在系统开发构架中有着很重要的地位和意义,MVC实现了业务逻辑和表示层的解耦。Observer模式是软件开发过程中必须要掌握的和使用的模式之一。Observer模式要解决的问题为:建立一个一(Subject)对多(Observer)的依赖关系,并且做到当“一”变化的时候,依赖这个“一”的多也能够同步改变。最常见的一个例子就是:对同一组数据进行统计分析时候,我们希望能够提供多种形式的表示(例如以表格进行统计显示、柱状图统计显示、百分比统计显示等)。这些表示都依赖于同一组数据,我们当然需要当数据改变的时候,所有的统计的显示都能够同时改变。Observer模式就是解决了这一个问题。

设计原则:为了交互对象之间的松耦合设计而努力。
出版者+订阅者=观察者模式
定义:定义了对象之间的一对多的依赖,这样一来,当一个对象改变状态,它的所有依赖者都会收到通知并自动更新。



主题对象(管理某些数据)------(一旦主题内的数据改变就会通知观察者)--------à观察者对象(狗对象,猫对象)
实现观察者模式的方法不止一种,但是以包含Subject和Observer接口的类设计的做法最常见。
气象站观察者模式类设计图:



注意这里的Observer的Update操作并不在Observer改变了Subject目标状态的时候就对自己进行更新,这个更新操作要延迟到Subject对象发出Notify通知所有Observer进行修改(调用Update)。

C++实现:
Subject.h头文件

#ifndef _SUBJECT_H_
#define _SUBJECT_H_
#include <list>
#include <string>
using namespace std;

class Observer;
class Subject  //主题接口
{

public:
virtual ~Subject();
virtual void Register(Observer* obv);
virtual void Remove(Observer* obv);
virtual void Notify();//当主题改变时,用这个方法通知所有的观察者

protected:

Subject();
private:

};
class WeatherData:public Subject
{
public:
WeatherData();
~WeatherData();
void Register(Observer* obv);//注册对象
void Remove(Observer* obv);
void Notify();//当主题改变时,用这个方法通知所有的观察者
void measurementsChanged();
void setMeasurements(float temperature,float humidity,float pressure);

protected:
private:

list<Observer* >* _obvs;  //保存注册的观察者
float temperature;
float humidity;
float pressure;
};

#endif


Subject.CPP源文件

#include "Subject.h"
#include "Observer.h"
#include <iostream>
#include <list>
using namespace std;

Subject::Subject()
{

}
Subject::~Subject()
{

}
void Subject::Register(Observer *obv)
{

}
void Subject::Remove(Observer *obv)
{

}
void Subject::Notify()
{

}

WeatherData::WeatherData()
{
_obvs=new list<Observer*>;
}
WeatherData::~WeatherData()
{

}

void WeatherData::Register(Observer *obv)
{
if(obv!=NULL)
_obvs->push_front(obv);
}
void WeatherData::Remove(Observer *obv)
{
if(obv!=NULL)

_obvs->remove(obv);
}
void WeatherData::Notify()
{
list<Observer*>::iterator it;
it=_obvs->begin();
for(;it!=_obvs->end();it++)
{
(*it)->Update(this->temperature,this->humidity,this->pressure);
}
}
void WeatherData::measurementsChanged()
{
Notify(); //数值更新,通知观察者

}
void WeatherData::setMeasurements(float temperature, float humidity, float pressure)
{
this->temperature=temperature;
this->humidity=humidity;
this->pressure=pressure;
measurementsChanged();
}


Observer.h头文件

//Observer.h
#ifndef _OBSERVER_H_
#define _OBSERVER_H_
#include "Subject.h"
#include <string>
using namespace std;
typedef string State;
class Observer
{
public:
virtual ~Observer();
virtual void Update(float temperature,float humidity,float pressure)=0;

};
class DisplayElement
{
public:
virtual ~DisplayElement();
virtual void display()=0;

};
/*当前状态公告板,实现Observer接口,所以可以从WeatherData对象中获取改变*/
/*规定所有的公告板必须实现DisplayElement接口*/
class CurrentConditionDisplay:public Observer,public DisplayElement
{

public:
CurrentConditionDisplay(Subject *sub);
~CurrentConditionDisplay();
void Update(float temperature,float humidity,float pressure);
void display();
private:
Subject *sub;
float temperature;
float humidity;

};

#endif


Observer.CPP源文件

#include "Subject.h"
#include "Observer.h"
#include <iostream>
#include <list>
using namespace std;
//typedef string state;
Observer:: ~Observer()
{

}
DisplayElement::~DisplayElement()
{

}
CurrentConditionDisplay::CurrentConditionDisplay(Subject *sub)
{
this->sub=sub;
sub->Register(this);
}

CurrentConditionDisplay::~CurrentConditionDisplay()
{
sub->Remove(this);
if(sub!=0)
delete sub;
}
void CurrentConditionDisplay::Update(float temperature,float humidity,float pressure)
{
this->temperature=temperature;
this->humidity=humidity;
display();
}
void CurrentConditionDisplay::display()
{
cout<<"Current condition: "<<this->temperature<<"F degrees and "<<this->humidity<<"% humidity"<<endl;
}


主函数main.CPP

#include "Subject.h"
#include "Observer.h"
#include <iostream>
using namespace std;
int main(int argc,char* argv[])
{

WeatherData *weatherData=new WeatherData(); //建立气象站
CurrentConditionDisplay *currentDisplay=new CurrentConditionDisplay(weatherData);//建立一个公告板,并注册一个观察者Observer,加入其中
weatherData->setMeasurements(80,65,65.4f);//气象站数据变化
weatherData->setMeasurements(81,78,65.4f); //setMeasurements调用Notify()通知所有的公告板更新数据并显示调用Update()函数,而公告板重载Observer的Update()
//从而达到所有的公告板随着weatherData对象即气象站的数据而更新显示
if (NULL != weatherData)
delete weatherData;

return 0;
}


复制搜索

复制搜索

复制搜索

复制搜索

复制搜索

复制搜索

复制搜索

复制搜索

复制搜索

复制搜索

复制搜索

复制搜索
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐