Observer模式

在面向对象程序设计中,通常会出现一种一对多的关系,当一个对象的关态发生改变时,所有依赖于它的对象都得到通知并被自动更新.

 

比如我们要统计朗讯的switch, router, mobile phone的market share,并分别用表格,柱状图和饼图显示出来,我们可以把market share的数据用一个类来管理,表格,柱状图和饼图分别各用一个类来管理,表格,柱状图和饼图三者之间是相互独立的,我们希望他们之间的耦合达到最小,以便复用.同时我们又希望当market share数据发生变化时,三个图可以实现自动更新,这时,我们就可以用observer模式来实现.

 

 observer parrtern UML

observer模式的优缺点:

  1. 目标和观察都之间耦合度小,一个目标仅仅知道它有一些观察者,目标不知道任何一个观察者属于那个类.同时观察都之间也基本上没有什么联系.
  2. 依赖准则和定义和维护要格外小心,防止在一个观察者中改变目标时引起错误的更新.

 下面是我实现的一个简单的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;                 
    }
   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值