1.引子
今天逛论坛,看到一个很实用的帖子,问的是子对象如何通知父对象?
代码是:
class A
{
bool flag;
void set_status()
{
flag = true;
}
};
class B
{
B()
{
A a;
a.flag = false;
}
bool get_a_status()
{
return a.flag;
}
};
int main()
{
B b;
while(1)
{
if(b.get_a_status())
{
printf("Yes, a is true\n");
break;
}
}
}
这里有个明显的问题就是父对象b要轮询子对象a的状态是不是true,但是最好的办法就是
子对象的状态变化了,自动通知父对象。这个要怎么做才好呢。使用事件?
下面有人建议用观察者模式。
这就引出了我初步学习观察者模式,并写下这篇很水的博客。
2.概念级学习
UML图。
根据这张图,我们写一下,论坛上的代码。
//Observer.h
#ifndef _Observer_
#define _Observer_
class Observer
{
public:
Observer(){}
virtual ~Observer(){}
virtual void Update(){}
};
#endif
//Object.h
#ifndef _Object_
#define _Object_
#include "Observer.h"
#include <list>
using namespace std;
class Object
{
public:
Object(){}
virtual ~Object(){}
void Attach(Observer * observer){m_obsservers.push_back(observer);}
void Remove(Observer * observer){m_obsservers.push_back(observer);}
void Notify()
{
std::list<Observer *>::iterator iter =m_obsservers.begin();
for(;iter != m_obsservers.end();iter++)
(*iter)->Update();
}
virtual void set_status(){}
virtual bool get_status(){}
private:
list<Observer *> m_obsservers;
};
#endif
//A.h
#ifndef _A_
#define _A_
#include "Object.h"
class A : public Object
{
public:
A(){}
virtual ~A(){}
bool flag;
void set_status();
bool get_status();
};
#endif
//B.h
#ifndef _B_
#define _B_
#include "A.h"
#include "Observer.h"
#include "Object.h"
#include <unistd.h>
#include <iostream>
class B:public Observer
{
private:
Object * m_object;
public:
B(Object * object):m_object(object)
{
/*m_object.set_status();*/
}
void Update();
bool get_a_status();
};
#endif
#include <iostream>
#include "A.h"
#include "B.h"
#include "Observer.h"
#include "Object.h"
using namespace std;
int main()
{
Object * object = new A();
Observer * observer1 = new B(object);
object->Attach(observer1);
object->set_status();
object->Notify();
object->set_status();
object->Notify();
delete object;
delete observer1;
//while(1)
//{
//if(b.get_a_status())
//{
//cout << "Yes, a is true"<<endl;
//}
//else
//cout << "NO, a is false" << endl;
//sleep(1);
//}
}
核心代码如上。实现了 A改变状态,通知B执行update函数的功能。
A继承于Object,Object里面实现了一个list <observer *> 来调用B。
A调用set_status()改变状态后,再调用Notify()通知给所有list<observer *>里的观察者,调用观察者的update。每一个观察者实体都是继承来自B的 ,所以实现了调用B实体的目的。
这样理解起来避免了 while循环查看,和sigal很像;
信号和槽好像就是封装了 观察者模式。
被调用者(被通知执行动作者)继承public has_slots<> ;
通知者 包含了signal0<> ToSniffer;
- myLoc.ToSniffer.connect(&mysniffer,&Sniffer::startSniffer);
- myTopo.ToSniffer.connect(&mysniffer,&Sniffer::startSniffer);
信号和槽的概念也是为了解决 父对象通知子对象来执行某函数的功能。
由此可见我们还是不要自己封装 observer类了,有现成的Sigslot使用。