在面向对象程序设计中,通常会出现一种一对多的关系,当一个对象的关态发生改变时,所有依赖于它的对象都得到通知并被自动更新.
比如我们要统计朗讯的switch, router, mobile phone的market share,并分别用表格,柱状图和饼图显示出来,我们可以把market share的数据用一个类来管理,表格,柱状图和饼图分别各用一个类来管理,表格,柱状图和饼图三者之间是相互独立的,我们希望他们之间的耦合达到最小,以便复用.同时我们又希望当market share数据发生变化时,三个图可以实现自动更新,这时,我们就可以用observer模式来实现.
observer模式的优缺点:
- 目标和观察都之间耦合度小,一个目标仅仅知道它有一些观察者,目标不知道任何一个观察者属于那个类.同时观察都之间也基本上没有什么联系.
-
依赖准则和定义和维护要格外小心,防止在一个观察者中改变目标时引起错误的更新.
下面是我实现的一个简单的observer模式,用于显于系统时间.
//
//下面是接口定义
//
#ifndef observer_h
#define observer_h
#include <iostream>
#include <list>
using namespace std;
class IObject;
class IObserver
{
public:
virtual ~IObserver(){};
virtual void Update( IObject* ) = 0;
protected:
IObserver(){}
};
class IObject
{
public:
virtual ~IObject(){};
virtual void Attach( IObserver* );
virtual void Detach( IObserver* );
virtual void Notify( void );
protected:
IObject(){};
private:
std::list< IObserver* > Observers;
typedef std::list< IObserver* >::iterator ObserverIter;
};
void IObject::Attach( IObserver *o )
{
Observers.push_back( o );
}
void IObject::Detach( IObserver *o )
{
ObserverIter it = Observers.begin();
ObserverIter end = Observers.end();
for( ; it != end; ++it )
{
if( ( *it ) == o )
Observers.remove( o );
}
}
void IObject::Notify()
{
ObserverIter it = Observers.begin();
ObserverIter end = Observers.end();
for( ; it != end; ++it )
{
( *it )->Update( this );
}
}
#endif
//
// 下面是具体类的定义与实现
//
#ifndef mytime_h
#define mytime_h
#include "observer.h"
#include <ctime>
class CTimeInfo : public IObject
{
public:
CTimeInfo(){};
virtual ~CTimeInfo(){};
time_t GetTime( void );
clock_t GetClock( void );
void Tick( void );
};
class CLocalTime : public IObserver
{
public:
CLocalTime( CTimeInfo* );
virtual ~CLocalTime();
virtual void Update( IObject* );
virtual void Draw( void );
private:
CTimeInfo *TimeInfo;
};
class CGMTime : public IObserver
{
public:
CGMTime( CTimeInfo* );
virtual ~CGMTime();
virtual void Update( IObject* );
virtual void Draw( void );
private:
CTimeInfo *TimeInfo;
};
//
// implement code
//
time_t CTimeInfo::GetTime()
{
return time( 0 );
}
clock_t CTimeInfo::GetClock()
{
return clock();
}
//
// 每隔一秒调用一次
//
void CTimeInfo::Tick()
{
Notify();
}
//
// 创建时在目标中注册观察者
//
CLocalTime::CLocalTime( CTimeInfo *timeInfo )
{
TimeInfo = timeInfo;
TimeInfo->Attach( this );
}
//
//当对象销毁时在目标中注销观察者
//
CLocalTime::~CLocalTime()
{
TimeInfo->Detach( this );
}
void CLocalTime::Update( IObject *o )
{
Draw();
}
void CLocalTime::Draw()
{
time_t t = TimeInfo->GetTime();
clock_t c = TimeInfo->GetClock();
struct tm *ptr_tm = localtime( &t );
cout<<"local time:"<<ptr_tm->tm_hour<<":"<<ptr_tm->tm_min<<":"<<ptr_tm->tm_sec<<endl;
}
CGMTime::CGMTime( CTimeInfo *o )
{
TimeInfo = o;
TimeInfo->Attach( this );
}
CGMTime::~CGMTime()
{
TimeInfo->Detach( this );
}
void CGMTime::Update( IObject *o )
{
Draw();
}
void CGMTime::Draw()
{
time_t t = time( 0 );
clock_t c = clock();
struct tm *ptr_tm = gmtime( &t );
cout<<"gm time:"<<ptr_tm->tm_hour<<":"<<ptr_tm->tm_min<<":"<<ptr_tm->tm_sec<<endl;
}
#endif
//
//使用说明
//
CTimeInfo *myTime = new CTimeInfo;
CLocalTime *localTime = new CLocalTime( myTime );
CGMTime *gmTime = new CGMTime( myTime );
clock_t cnt = 0;
int duration_current = 0;
int duration_old = 0;
int flag = 0; // 一个时钟周期可能会多次调用system( "cls" );
clock_t begin_clock = clock();
clock_t current_clock;
while( 1 )
{
current_clock = clock();
duration_current = ( current_clock - begin_clock )/1000;
// 过去了一秒钟
if( duration_current > duration_old )
flag = 0;
if( (0 == flag) && (0 == (current_clock - begin_clock)%1000) )
{
duration_old = duration_current;
flag = 1;
system( "cls" );
myTime->Notify();
}
if( 100 == duration_current )
break;
}