观察者模式是23种设计模式中很重要也很常用的模式,在软件开发中我们经常会遇到。
观察者模式的定义:定义了对象间的一对多的依赖关系,让多个观察者对象同时监听某一个主题对象(被观察者)。当主题对象的状态发生更改时,会通知所有观察者,让它们能够自动更新。
在实际的应用中我们常常使用观察者模式来解决软件中的消息通信的问题。例如,我们有一个QT编写的QWidget应用,这个应用包含了多个QWidget窗口(观察者),应用会实时地从串口(主题对象)获得一些数据,各个QWidget窗口都需要这些数据来更新自己。
UML结构图如下:
下面我用伪码来表述上面的例子。
//抽象的串口
class IWidget //需要更新的窗口的基类
class AbstractSerial
{
public:
virtual ~AbstractSerial() {}//虚析构函数
public:
virtual void Add(IWidget *) = 0; // 注册观察者,这里就是注册那些需要刷新的窗口
virtual void Remvoe(IWidget *) = 0; // 注销观察者
virtual void Notify() = 0; // 通知观察者,这里就是让窗口自己刷新
};
//实际的串口
class Serial : public AbstractSerial
{
private:
list<IWidget *> m_widgets;//观察者列表,这里就是窗口列表
int m_data;//串口得到的数据
public:
void Add(IWidget *pWidget) {
m_widgets.push_back(pWidget);
}
void Remvoe(IWidget *pWidget) {
m_widgets.remove(pWidget);
}
void Notify() {
list<IWidget *>::iterator it = m_widgets.begin();
while (it != m_widgets.end()) {
(*it)->Update(m_data);
++it;
}
};
//注:在实际应用中,其实可以不需要写AbstractSerial这个类,可以在具体类中定义那三个方法即可。
//这里重要的是Serial类中需要维护一个IWidget类的指针列表
//抽象的观察者,这里就是所有窗口的基类
class IWidget
{
public:
virtual ~IWidget() {}
public:
virtual void Update(int data) = 0;//自我更新
};
//具体的观察者,可以有很多
class Widget1 : public IWidget
{
public:
void Update(int data){
std::cout<<"用数据进行自我更新"<<std::endl;
}
};
class Widget2 : public IWidget
{
//.......................
};
class Widget3 : public IWidget
{
//.......................
};
//应用
int main()
{
//创建主题,这里是创建串口
Serial *pSerial = new Serial ();
//创建观察者,这里就是实际需要数据的窗口
IWidget *pWidget1 = new Widget1 ();
IWidget *pWidget2 = new Widget2 ();
IWidget *pWidget3 = new Widget3 ();
//把这些观察者记录下来
pSerial->Add(pWidget1);
pSerial->Add(pWidget2);
pSerial->Add(pWidget3);
//有数据就通知它们更新吧!
pSerial->Notify();
return 0;
}
现在返回那张UML图我们再来看
结合到我们的例子和观察者模式的定义,其中稳定的部分就是我们的IWidget类和AbstractSerial类。变化的部分是我们的具体的Serial类和Widget1,2,3类。我们是通过在Serial类中维护一个IWidget类指针的list来让其子类自动更新的。
最后,如果理解的有偏差,还请指出!