[行为模式]head first 设计模式之观察者模式(observer)

1 定义:
观察者模式(有时又被称为发布/订阅模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实作事件处理系统。
[color=red]定义对象间的一种一对多的以来关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
别名:依赖(Dependennts),发布-订阅(Publish-Subscribe)[/color]

2 设计原则
[size=medium][color=red]为了交互对象之间的松耦合设计而努力,简单点讲就是出版者+订阅者=观察者模式。[/color][/size]

3 参与类别
参与本模式的各类别列出如下。成员函式以模拟的方式列出。
3.1 抽象目标类别
此抽象类别提供一个接口让观察者进行添附与解附作业。此类别内有个不公开的观察者串炼,并透过下列函式(方法)进行作业
[b] 添附(Attach):[/b]新增观察者到串炼内,以追踪目标物件的变化。
[b]解附(Detach):[/b]将已经存在的观察者从串炼中移除。
[b]通知(Notify):[/b]利用观察者所提供的更新函式来通知此目标已经产生变化。
添附函式包涵了一个观察者物件参数。也许是观察者类别的虚拟函式(即更新函式),或是在非面向对象的设定中所使用的函式指标(更广泛来讲,函式子或是函式物件)。

3.2 目标类别
此类别提供了观察者欲追踪的状态。也利用其源类别(例如前述的抽象目标类别)所提供的方法,来通知所有的观察者其状态已经更新。此类别拥有以下函式
取得状态[b](GetState):[/b]回传该目标物件的状态。

3.3 抽象观察者接口
抽象观察者类别是一个必须被实做的抽象类别。这个类别定义了所有观察者都拥有的更新用接口,此接口是用来接收目标类别所发出的更新通知。此类别含有以下函式
更新(Update):会被实做的一个抽象(虚拟)函式。

3.4 观察者类别
这个类别含有指向目标类别的参考(reference),以接收来自目标类别的更新状态。此类别含有以下函式
[b]更新(Update):[/b]是前述抽象函式的实做。当这个函式被目标物件呼叫时,观察者物件将会呼叫目标物件的取得状态函式,来其所拥有的更新目标物件资讯。
每个观察者类别都要实做它自己的更新函式,以应对状态更新的情形。
当目标物件改变时,会通过呼叫它自己的通知函式来将通知送给每一个观察者物件,这个通知函式则会去呼叫已经添附在串炼内的观察者更新函式。通知与更新函式可能会有一些参数,好指明是目前目标物件内的何种改变。这么作将可增进观察者的效率(只更新那些改变部份的状态)。

4 观察者模式的优点
观察者与被观察者之间是属于轻度的关联关系,并且是抽象耦合的,这样,对于两者来说都比较容易进行扩展。
观察者模式是一种常用的触发机制,它形成一条触发链,依次对各个观察者的方法进行处理。但同时,这也算是观察者模式一个缺点,由于是链式触发,当观察者比较多的时候,性能问题是比较令人担忧的。并且,在链式结构中,比较容易出现循环引用的错误,造成系统假死。

[img]http://t25-1.yunpan.360.cn/p/800-600.fb8a80c738c77348b1976d0b0c7198c5c31578c9.83a2ab.jpg?t=a344bfb34b846467f2df389c48ad5ce8&d=20130821[/img]



#ifndef OBSERVER_H
#define OBSERVER_H

#include <iostream>
#include <list>
using namespace std;

//观察者模式
namespace Observer
{

//
class Observer
{
public:
virtual void update(float temp, float humidity, float pressure) = 0;
};
//
typedef list<Observer*> ObserverList;

class Subject
{
public:
virtual void registerObserver(Observer* ob) = 0 ;
virtual void removeObserver(Observer* ob) = 0;
virtual void notifyObserver() = 0;
};

class WeatherData : public Subject
{
public:
virtual void registerObserver(Observer* ob)
{
m_ObserverList.push_back(ob);
}

virtual void removeObserver(Observer* ob)
{
ObserverList::const_iterator itr = find(ob);
if ( itr != m_ObserverList.end() )
{
m_ObserverList.erase(itr);
}
}

virtual void notifyObserver()
{
ObserverList::const_iterator itr = m_ObserverList.begin();
ObserverList::const_iterator end = m_ObserverList.end();
for ( ; itr != end; ++itr)
{
if ( *itr != NULL)
{
(*itr)->update(m_Tempperature, m_Humidity, m_Pressure);
}
}
}

void measurementsChanged()
{
notifyObserver();
}

void setMeasurements(float tempperature, float humidity, float pressure)
{
this->m_Tempperature = tempperature;
this->m_Humidity = humidity;
this->m_Pressure = pressure;
measurementsChanged();
}

private:
ObserverList::const_iterator find( const Observer* ob)
{
ObserverList::const_iterator itr = m_ObserverList.begin();
ObserverList::const_iterator end = m_ObserverList.end();
for ( ; itr != end; ++itr)
{
if ( *itr == ob)
{
return itr;
}
}

return end;
}

private:
ObserverList m_ObserverList;
float m_Tempperature;
float m_Humidity;
float m_Pressure;
};

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

//
class CurrentConditionDisplay : public Observer, public DisplayElement
{
public:
CurrentConditionDisplay(Subject* weatherData)
: m_Humidity(0),
m_Tempperature(0.0f),
m_WeatherData(NULL)
{
if (weatherData != NULL)
{
if (m_WeatherData!=NULL)
{
delete m_WeatherData;
m_WeatherData = NULL;
}

this->m_WeatherData = weatherData;
this->m_WeatherData->registerObserver(this);
}
}
virtual ~CurrentConditionDisplay()
{
if (m_WeatherData != NULL)
{
delete m_WeatherData;
m_WeatherData = NULL;
}
}
virtual void update(float temp, float humidity, float pressure)
{
this->m_Tempperature = temp;
this->m_Humidity = humidity;
display();
}

virtual void display()
{
cout << "Current conditions: " << m_Tempperature << "F degree and " << m_Humidity << "% humidity" <<endl;
}

private:
float m_Tempperature;
float m_Humidity;
Subject* m_WeatherData;
};

class WeatherStation
{
public:
void run()
{
WeatherData* weatherData = new WeatherData();

CurrentConditionDisplay* currentDisplay1 = new CurrentConditionDisplay(weatherData);
CurrentConditionDisplay* currentDisplay2 = new CurrentConditionDisplay(weatherData);
CurrentConditionDisplay* currentDisplay3 = new CurrentConditionDisplay(weatherData);
//StatisticsDisplay* statisticsDisplay = new StatisticsDisplay(weatherData);
//ForecastDisplay* forecastDisplay = new ForecastDisplay(weatherData);

weatherData->setMeasurements(80, 65, 30.4f);
weatherData->setMeasurements(82, 70, 29.2f);
weatherData->setMeasurements(78, 90, 29.2f);

if (weatherData != NULL)
{
delete weatherData;
}

if (currentDisplay1 != NULL)
{
delete currentDisplay1;
}

if (currentDisplay2 != NULL)
{
delete currentDisplay2;
}

if (currentDisplay3 != NULL)
{
delete currentDisplay3;
}
}
};

}//namespace Observer

#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值