Observer 设计模式与CEGUI 中的消息响应处理
Jingwenlai 2009-12-10
Observer 设计模式
可以将观察者(Observer) 设计模式理解成( 报刊- 订阅者) 的形式,订阅者只需注册后,一旦报刊有更新,则会自动通知到订阅者。
这种模式可应用的场合较多,如在《Head first design pattern 》中所举的例子是用天气预报更新的例子。
近期在看CEGUI 代码的时候,发现其消息响应处理机制与Observer 很类似,简单将其类说明如下(参照下图):
CEGUI 中所有控件的基类都是CEGUIWindow, 而对于消息的处理,Window 派生于EventSet, EventSet 实际只是用一个multiMap 保存了对于一个Window 的多个Event 。
EVENT : 实际上对消息的处理是通过Event 类来处理的。Event 类与SubscriberSlot 相关联,Event 对SubscriberSlot 进行注册,并执行自己的notify 的时候执行所有注册的SubscriberSlot 。(此处CEGUI 的实现均使用operator() 来代替相应的notify 及update 操作).
SubscriberSLOT : 而对于SubscriberSlot 而言,真正执行相应操作是其成员slotFunctorBase ,基于此SlotFunctorBase 派生出多种回调形式:FreeFunctionSlot,MemberFunctionSlot 等。这样扩展性得到了提高,后面要处理其他形式的回调函数的时候,只需派生SlotFunctorBase 基类即可。另外,在实现这些回调函数形式的时候,均采用了类似于
Bool functionName(const EventArgs&)
的形式,这也就是为什么CEGUI 使用的时候,定义回调函数都需要返回bool 型,而且参数是const EventArgs& 的形式的原因。
EventArgs :还有另一批基于EventArgs 的类实际上是用于Event 以及SubscribeSlot 之间用于传递参数的,基于EventArgs 类 派生了一系列诸如处理键盘鼠标及窗口等的消息。而且CEGUI 在内部定义了自己的一套枚举类型用于定义这些消息,这样做的好处正如CEGUI 文档所述:可以独立于各种不同的外部封装窗口的API ,如Win32 Framework,MFC,Qt,wxWidget 等不同类型的UI 库,可以将其处理消息转换成CEGUI 内部的枚举型后再用CEGUI::System::injectXXX 输入给CEGUI 进行内部处理。
对应的图如下:(画得不准确,作为上述描述的参考吧)
现在对CEGUI 还不算太熟,看其代码本意是想对现有的代码进行设计上的改进。开源代码的流行及广泛接受总会有其原因。Code Review 的人越多,bug 出现的机会越少。
Reference:
http://www.vincehuston.org/dp/observer.html
CEGUI source code