观察者模式(又名发布-订阅模式)主要使用场景:
当一个对象的状态发生改变时,所有依赖它的对象都得到通知,并被自动更新.
- 目标对象类:
class Subject
{
public:
~Subject(){}
virtual void Attach(Observer*);//增加一个观察者(即订阅)
virtual void Detach(Observer*);//删去一个观察着(即退订)
virtual void Notify();//通知观察者更新数据
protected:
Subject(){};
private:
vector<Observer*> m_pObservers;//保存观察者列表
};
void Subject::Attach(Observer* obs)
{
m_pObservers.push_back(obs);
}
void Subject::Detach(Observer* obs)
{
vector<Observer*>::iterator it = find(m_pObservers.begin(), m_pObservers.end(), obs);
if(it != m_pObservers.end())
{
m_pObservers.erase(it);
}
}
void Subject::Notify()
{
vector<Observer*>::iterator it;
for(it = m_pObservers.begin(); it!=m_pObservers.end(); ++it)
{
(*it)->Update(this);
}
}
- 观察者类结构:
class Observer
{
public:
~Observer(){}
virtual void Update(Subject*)=0;//具体的更新操作
protected:
Observer(){}
};
看一个时钟的例子,假如我们有一个定时器,每隔一秒钟会更新一次时间,另外,我们有一个显示时间的类,该类实时通过模拟窗口显示当前的时间.
定时器类ClockTimer, 其中保存了时间(时-分-秒),另外,定时器每隔一秒钟会执行Tick(),在Tick中,会出发对观察者(时间显示类DigitalClock)的update操作.
class ClockTimer: public Subject
{
public:
ClockTimer(int hour, int min, int sec)
{
m_hour = hour;
m_min = min;
m_sec = sec;
}
int GetHour()
{
return m_hour;
}
int GetMin()
{
return m_min;
}
int GetSec()
{
return m_sec;
}
void Tick();//定时器定时增加一秒
private:
int m_hour;
int m_min;
int m_sec;
};
void ClockTimer::Tick()
{
++m_sec;
Notify();
}
模拟时间显示类DigitalClock,它在构造时保存了当前定时器的指针m_pClock,订阅和退订操作在DigitalClock的构造与析构时完成.最后在update时,通过定时器指针获取到定时器更新后的时间,并进行显示.
class DigitalClock: public Observer//模拟时间显示类
{
public:
DigitalClock(ClockTimer* pClock)
{
m_pClock = pClock;
m_pClock->Attach(this);//订阅
}
virtual ~DigitalClock()
{
m_pClock->Detach(this);//退订
};
virtual void Update(Subject* sub)
{
//检查时钟是否正确
if(sub == m_pClock)
{
Draw();
}
}
virtual void Draw()
{
int hour, min, sec;
hour = m_pClock->GetHour();
min = m_pClock->GetMin();
sec = m_pClock->GetSec();
cout<<"当前时间时:"<<hour<<"-"<<min<<"-"<<sec<<endl;
}
private:
ClockTimer* m_pClock;
};
- 完整代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Subject;
class Observer
{
public:
~Observer(){}
virtual void Update(Subject*)=0;
protected:
Observer(){}
};
class Subject
{
public:
~Subject(){}
virtual void Attach(Observer*);
virtual void Detach(Observer*);
virtual void Notify();
protected:
Subject(){};
private:
vector<Observer*> m_pObservers;
};
void Subject::Attach(Observer* obs)
{
m_pObservers.push_back(obs);
}
void Subject::Detach(Observer* obs)
{
vector<Observer*>::iterator it = find(m_pObservers.begin(), m_pObservers.end(), obs);
if(it != m_pObservers.end())
{
m_pObservers.erase(it);
}
}
void Subject::Notify()
{
vector<Observer*>::iterator it;
for(it = m_pObservers.begin(); it!=m_pObservers.end(); ++it)
{
(*it)->Update(this);
}
}
class ClockTimer: public Subject
{
public:
ClockTimer(int hour, int min, int sec)
{
m_hour = hour;
m_min = min;
m_sec = sec;
}
int GetHour()
{
return m_hour;
}
int GetMin()
{
return m_min;
}
int GetSec()
{
return m_sec;
}
void Tick(); //定时器定时增加一秒
private:
int m_hour;
int m_min;
int m_sec;
};
void ClockTimer::Tick()
{
++m_sec;
Notify();
}
class DigitalClock: public Observer //模拟时间显示类
{
public:
DigitalClock(ClockTimer* pClock)
{
m_pClock = pClock;
m_pClock->Attach(this); //订阅
}
virtual ~DigitalClock()
{
m_pClock->Detach(this); //退订
};
virtual void Update(Subject* sub)
{
//检查时钟是否正确
if(sub == m_pClock)
{
Draw();
}
}
virtual void Draw()
{
int hour, min, sec;
hour = m_pClock->GetHour();
min = m_pClock->GetMin();
sec = m_pClock->GetSec();
cout<<"当前时间时:"<<hour<<"-"<<min<<"-"<<sec<<endl;
}
private:
ClockTimer* m_pClock; //保存当前对定时器
};
int main()
{
ClockTimer* pTimer = new ClockTimer(12, 10, 50);
DigitalClock* pShowTime = new DigitalClock(pTimer);
pTimer->Tick();
pTimer->Tick();
pTimer->Tick();
delete pShowTime;
delete pTimer;
return 0;
}
最后执行结果如下: