观察者模式有一个不足,在于所有观察者必须派生于同一个基类,并且实现方法Update,而在实际应用中,往往不能满足这种条件,因为不同的观察者可能是毫不相关的两个类,并且可能不会提供Update方法,解决的方法就是使用事件委托。
C++中没有提供委托模型,需要自己构造,我们最容易想到的就是使用函数指针,而要取得类的成员函数指针,我们需要如下定义:
class A
{
public:
void Func(void) {}
};
void (A::*pFunc)(void)=&A::Func;
其意义是pFunc指向类A的成员函数Func。当我们调用时也许普通函数指针不同,调用方法如下:
A a;
(a.*pFunc)();
A *p=&a;
(p->*pFunc)();
为了实现我们的函数指针可以指向不同类的成员函数,可以将函数指针封装到一个模板类中。实际应用中,我们会使用不同类的函数指针,同时又需要将这些类进行统一管理,即放在一个容器内,而容器中存放的要求是同一类型,模板类不满足这个条件。要实现这种功能,可以利用类的多态性,即委托模板类继承于一个只提供接口的基类,容器中存放基类的指针,这样无论我们的模板类采用什么类型,都可通过基类指针来访问。
实现代码如下:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
//定义一个基类实现接口
class IDelegateHandler
{
public:
~IDelegateHandler() {}
virtual void Update()=0;
};
//定义具体的事件委托类
//指向类成员函数的委托类
template<class T>
class DelegateHandle:public IDelegateHandler
{
private:
T *m_pT;
void (T::*m_pFunc)(void);
public:
DelegateHandle(T *t,void (T::*func)(void))
:m_pT(t)
,m_pFunc(func)
{
}
void Update()
{
(m_pT->*m_pFunc)();
}
};
class Subject
{
string m_action;
public:
void SetAction(string action)
{
m_action=action;
}
string GetAction(void)
{
return m_action;
}
public:
virtual void Notify(void)=0;
};
class boss:public Subject
{
public:
vector<IDelegateHandler *> pUpdate;
public:
void Notify()
{
vector<IDelegateHandler *>::iterator pos;
for (pos=pUpdate.begin();pos!=pUpdate.end();++pos)
{
(*pos)->Update();
}
}
};
class ObserverA
{
private:
Subject *m_pSubject;
public:
ObserverA(Subject *subject)
{
m_pSubject=subject;
}
public:
void UpdateA(void)
{
cout<<m_pSubject->GetAction()<<"this is A"<<endl;
}
};
class ObserverB
{
private:
Subject *m_pSubject;
public:
ObserverB(Subject *subject)
{
m_pSubject=subject;
}
void UpdateB()
{
cout<<m_pSubject->GetAction()<<"this is B"<<endl;
}
};
void main()
{
boss b;
ObserverA oa(&b);
ObserverB ob(&b);
DelegateHandle<ObserverA> ha(&oa,&ObserverA::UpdateA);
DelegateHandle<ObserverB> hb(&ob,&ObserverB::UpdateB);
b.pUpdate.push_back(&ha);
b.pUpdate.push_back(&hb);
b.SetAction("boss is comming,");
b.Notify();
}