观察者模式,是我们在开发过程中经常会遇到或者使用的设计模式。
比较常见的,我们在GUI库里便能看到其身影,譬如:键盘敲击事件后,需要将这一事件通知到所有观测键盘事件的对象。但凡涉及到这种一对多的通知,基本上都是观察者模式的应用。
?
?
我们经常使用的开发库中经常会存在这种模式,但是实现方式却不尽相同。所以,了解c/c++语言下观察者模式的实现方式,对于我们学习和掌握各种开源库将非常有帮助。一旦了解到该模式的存在,对整个代码会更增加一层了解和信心。
?
下面,我以我所知道的几种方式来分别实现一个非常简单的观察者模式,以示语言特性和该模式的一些特征。
假设,Subject会接受整数A和B,同时该Subject绑定了若干个Observer,在接受到整数A和B之后,需要及时通知所有Observer(例子里作为观察者的Adder和Muler皆简单输出A和B的和以及乘积)
?
先看c风格的代码实现:
?
#include
// c style
int Add(int iA, int iB)
{
printf(Add(%d,%d)=%d
, iA, iB, iA + iB);
return iA + iB;
}
int Mul(int iA, int iB)
{
printf(Mul(%d,%d)=%d
, iA, iB, iA * iB);
return iA * iB;
}
typedef int (*fpCallBack)(int iA, int iB);
int main()
{
fpCallBack fpcb[2] = {&::Add, &::Mul};
fpcb[0](1, 2);
fpcb[1](1, 2);
return 0;}
?
这种方式间接明了,一路了然。c的风格就是这样的,不同的人写一小段代码,可能都大同小异。
?
#include
#include
// cpp style1 struct IObserver1 { virtual int OnAB(int iA, int iB)=0; }; struct Subject1 { void AddObserver(IObserver1*pObserver) { m_vecObserver.push_back(pObserver); } void Notify(int iA, int iB) { for (unsigned i = 0; i < m_vecObserver.size(); ++i) { m_vecObserver[i]->OnAB(iA, iB); } } std::vector
m_vecObserver; }; struct Adder1 : public IObserver1 { virtual int OnAB(int iA, int iB) { printf(Add1(%d,%d)=%d , iA, iB, iA + iB); return iA + iB; } }; struct Muler1 : public IObserver1 { virtual int OnAB(int iA, int iB) { printf(Mul1(%d,%d)=%d , iA, iB, iA * iB); return iA * iB; } }; int main() { Subject1 subj1; Adder1 adder1; Muler1 muler1; subj1.AddObserver(&adder1); subj1.AddObserver(&muler1); subj1.Notify(1, 2); return 0; }
这个也是比较显而易见的方式,定义一个虚基类,各个观察者必须继承并实现该接口,以方便管理并及时收到通知。这种方式的可读性比较好,但是耦合性比较大。
?
?
再看一个c++实现的方式:
?
#include
#include
// cpp style2 struct IObserver2 { }; typedef int (IObserver2::*Ofp)(int iA, int iB); struct Subject2 { void AddObserver(IObserver2*pObj, Ofp fp) { m_vecpObj.push_back(pObj); m_vecOfp.push_back(fp); } void Notify(int iA, int iB) { for (unsigned i = 0; i < m_vecpObj.size(); ++i) { (((IObserver2*)m_vecpObj[i])->*m_vecOfp[i])(iA, iB); } } std::vector
m_vecpObj; std::vector
m_vecOfp; }; struct Adder2 : public IObserver2 { int OnAB(int iA, int iB) { printf(Add2(%d,%d)=%d , iA, iB, iA + iB); return iA + iB; } }; struct Muler2 : public IObserver2 { int OnAB(int iA, int iB) { printf(Mul2(%d,%d)=%d , iA, iB, iA * iB); return iA * iB; } }; int main() { Subject2 subj2; Adder2 adder2; Muler2 muler2; subj2.AddObserver(&adder2, (Ofp)&Adder2::OnAB); subj2.AddObserver(&muler2, (Ofp)&Muler2::OnAB); subj2.Notify(1, 2); return 0 }
这个方法是基于类的成员函数指针来实现的,同样是继承,但是并不要求Observer类必须实现制定的虚函数,只需要保证有相同的成员函数签名。一个Observer类甚至能容纳多个Observer方法。这种方式相对前一种方式更灵活一点,但是同样要求继承一个基类,还是有一定的耦合性。
?
?
再看最后一个,c++11的版本
?
// cpp11
typedef std::function
IntOpFun;
struct Subject3
{
void AddObserver(IntOpFun of)
{
m_vecOf.push_back(of);
}
void Notify(int iA, int iB)
{
for (auto iter = m_vecOf.begin(); iter != m_vecOf.end(); ++iter)
{
(*iter)(iA, iB);
}
}
std::vector
m_vecOf; }; struct Adder3 { int OnAB(int iA, int iB) { printf(Add3(%d,%d)=%d , iA, iB, iA + iB); return iA + iB; } }; struct Muler3 { int OnAB(int iA, int iB) { printf(Mul3(%d,%d)=%d , iA, iB, iA * iB); return iA * iB; } }; int main() { Subject3 subj; Adder3 adder; Muler3 muler; subj.AddObserver(std::bind(&Adder3::OnAB, &adder, std::placeholders::_1, std::placeholders::_2)); subj.AddObserver(std::bind(&Muler3::OnAB, &muler, std::placeholders::_1, std::placeholders::_2)); subj.Notify(1, 2); return 0; }
这种方式不需要继承基类,不需