观察者(发布-订阅)模式浅析

来源:互联网 发布:ubuntu apt get本地源 编辑:程序博客网 时间:2024/05/21 10:11

观察者模式(又名发布-订阅模式)主要使用场景:

当一个对象的状态发生改变时,所有依赖它的对象都得到通知,并被自动更新.

  • 目标对象类:

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;}

最后执行结果如下: