观察者(发布-订阅)模式浅析
来源:互联网 发布: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;}
最后执行结果如下:
- 观察者(发布-订阅)模式浅析
- 浅析JavaScript设计模式——发布-订阅/观察者模式
- 观察者模式--发布/订阅模式
- 观察者模式(也就是发布订阅模式)
- 观察者模式之二 -发布 订阅模式
- 观察者模式 (发布-订阅模式)
- 8. 观察者模式-发布订阅模式
- 观察者模式(又叫发布-订阅模式)
- 观察者模式与发布/订阅模式区别
- 观察者模式(发布订阅模式)
- 观察者模式与发布/订阅模式区别
- 发布订阅模式(观察者模式)
- 观察者模式与发布/订阅模式区别
- 发布-订阅模式(观察者模式)
- 观察者模式与发布订阅者模式
- 观察者模式(发布订阅模式)
- java设计模式-观察者(发布-订阅)模式
- 观察者模式(发布订阅模式)
- 4.5 数组,模板类vector和array的比较
- 如何去掉a标签的下划线
- Solution of Vim E303 Error under Win 7
- 改写linux窗口程序设计的Qt例子
- Oracle存储过程
- 观察者(发布-订阅)模式浅析
- 我也来读jquery
- 实际用户ID,有效用户ID与保存设置用户ID(转自:http://blog.csdn.net/dlutbrucezhang/article/details/8806015)
- 迭代跟递归算法
- 用Python开发自动化测试脚本
- 究竟几个CPU?
- Linux C学习笔记-排序算法1-插入排序
- 观《哈佛大学公开课:构建动态网站》有感
- python来进行UI自动化测试