// observer.h
#ifndef OBSERVER_H_
#define OBSERVER_H_
#include <list>
using namespace std;
class CAspect
{
CAspect()
{
}
virtual ~CAspect()
{
}
};
class CSubject;
// 观察者
class CObserver
{
protected:
CObserver()
{
}
public:
virtual ~CObserver()
{
}
// 目标变化时的更新接口,参数1指明是哪一个目标发生变化,因为可能一个观察者会观察多个目标,参数2传递观察者感兴趣的方面
virtual void Update(CSubject* poTheChangedSubject, CAspect* poInterest = NULL) = 0;
};
// 被观察者
class CSubject
{
private:
std::list<CObserver*> m_lstObservers; // 目标知道它的观察者
protected:
CSubject()
{
}
public:
virtual ~CSubject()
{
}
void Attach(CObserver* poObserver, CAspect* poInterest = NULL); // 注册一个观察者,指定其感兴趣的方面
void Detach(CObserver* poObserver, CAspect* poInterest = NULL);// 删除一个观察者
void Notify(CAspect* poInterest = NULL);
};
class CClockTimer : public CSubject
{
private:
// subject state
char m_i8Hour;
char m_i8Minute;
char m_i8Second;
public:
CClockTimer()
{
}
virtual ~CClockTimer()
{
}
void SetHour(char i8Hour);
void SetMinute(char i8Minute);
void SetSecond(char i8Second);
int GetHour();
int GetMinute();
int GetSecond();
void Tick();
};
class CDigitalClock : public CObserver
{
private:
CClockTimer* m_poSubject; // 观察的目标
// observer state,与目标的状态保持一致。也可以作为局部变量
char m_i8Hour;
char m_i8Minute;
char m_i8Second;
public:
CDigitalClock(CClockTimer* poSubject)
{
m_poSubject = poSubject;
m_poSubject->Attach(this, NULL);
}
virtual ~CDigitalClock()
{
m_poSubject->Detach(this, NULL);
}
virtual void Update(CSubject* poTheChangedSubject, CAspect* poInterest = NULL);
private:
void Draw();
};
class CAnalogClock : public CObserver
{
private:
CClockTimer* m_poSubject; // 观察的目标
public:
CAnalogClock(CClockTimer* poSubject)
{
m_poSubject = poSubject;
m_poSubject->Attach(this, NULL);
}
virtual ~CAnalogClock()
{
m_poSubject->Detach(this, NULL);
}
virtual void Update(CSubject* poTheChangedSubject, CAspect* poInterest = NULL);
private:
void Draw();
};
#endif /* OBSERVER_H_ */
// observer.cpp
#include <iostream>
#include <time.h>
#include "observer.h"
void CSubject::Attach(CObserver* poObserver, CAspect* poInterest)
{
m_lstObservers.push_back(poObserver);
}
void CSubject::Detach(CObserver* poObserver, CAspect* poInterest)
{
m_lstObservers.remove(poObserver);
}
void CSubject::Notify(CAspect* poInterest)
{
list<CObserver*>::iterator iter;
for (iter = m_lstObservers.begin(); iter != m_lstObservers.end(); ++iter)
{
(*iter)->Update(this, NULL);
}
}
void CClockTimer::SetHour(char i8Hour)
{
m_i8Hour = i8Hour;
}
void CClockTimer::SetMinute(char i8Minute)
{
m_i8Minute = i8Minute;
}
void CClockTimer::SetSecond(char i8Second)
{
m_i8Second = i8Second;
}
int CClockTimer::GetHour()
{
return m_i8Hour;
}
int CClockTimer::GetMinute()
{
return m_i8Minute;
}
int CClockTimer::GetSecond()
{
return m_i8Second;
}
void CClockTimer::Tick()
{
time_t t = time(NULL);
struct tm* local = localtime(&t);
SetHour(local->tm_hour);
SetMinute(local->tm_min);
SetSecond(local->tm_sec);
Notify();
}
void CDigitalClock::Update(CSubject* poTheChangedSubject, CAspect* poInterest)
{
if (poTheChangedSubject == m_poSubject)
{
Draw();
}
}
void CDigitalClock::Draw()
{
// 从目标获取状态信息
m_i8Hour = m_poSubject->GetHour();
m_i8Minute = m_poSubject->GetMinute();
m_i8Second = m_poSubject->GetSecond();
cout << (int) m_i8Hour << "/" << (int) m_i8Minute << "/" << (int) m_i8Second << endl;
}
void CAnalogClock::Update(CSubject* poTheChangedSubject, CAspect* poInterest)
{
if (poTheChangedSubject == m_poSubject)
{
Draw();
}
}
void CAnalogClock::Draw()
{
char i8Hour = m_poSubject->GetHour();
char i8Minute = m_poSubject->GetMinute();
char i8Second = m_poSubject->GetSecond();
cout << (int) i8Hour << ":" << (int) i8Minute << ":" << (int) i8Second << endl;
}
int main()
{
CClockTimer* poTimer = new CClockTimer();
CDigitalClock* poDigitalClock = new CDigitalClock(poTimer);
CAnalogClock* poAnalogClock = new CAnalogClock(poTimer);
// 有两个观察者
for (int i = 0; i < 4; ++i)
{
poTimer->Tick();
sleep(2);
}
delete poAnalogClock;
// 只剩一个观察者
for (int i = 0; i < 4; ++i)
{
poTimer->Tick();
sleep(2);
}
delete poDigitalClock;
// 无观察者
for (int i = 0; i < 4; ++i)
{
poTimer->Tick();
sleep(2);
}
delete poTimer;
return 0;
}
// g++ observer.cpp -o main -g -Wall