发布-订阅模式核心代码练习:
实现以下参与者:
EventObject
事件对象,用于参数传递
EventSource
事件源,用于触发事件
SubscriberTemplate
订阅器模板,保存客户代码
特殊需求:采用模板实现可定制的客户代码。
心得:
1、为了在 SubscriberTemplate 层面使 invoker 的类型无关,使用了 模板构造函数 和 MemberFunctionBounder ,将 invoker 的类型确定时机推到了 MemberFunctionBounder 层。
2、为了能在 SubscriberTemplate 调用客户代码,将 invoker 无关的接口抽象,形成 FunctionBounderBase 层。
3、为了保证 SubscriberTemplate 在赋值、拷贝、删除的时候对 bounder 对象的管理, 在 FunctionBounderBase 层添加了 clone 方法。
扩展:
1、支持非成员函数的客户代码。
2、支持非返回值的客户代码。
3、完善事件触发机制,添加注册、查找事件的功能。
// 123.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <vector> template<typename Ret,typename Arg> struct FunctionBounderBase { virtual ~FunctionBounderBase(){} virtual Ret operator ()(Arg) = 0; virtual FunctionBounderBase<Ret,Arg>* clone() = 0; }; template<typename T, typename Ret,typename Arg> struct MemberFunctionBounder : FunctionBounderBase<Ret, Arg> { typedef Ret (T::*MemberFunction)(Arg); MemberFunctionBounder(T* _invoker, MemberFunction _mem_func) : invoker( _invoker) , mem_func( _mem_func) { } Ret operator()(Arg arg) { return (invoker->*mem_func)(arg); } FunctionBounderBase<Ret,Arg>* clone() { return new MemberFunctionBounder<T,Ret,Arg>( invoker, mem_func); } MemberFunction mem_func; T* invoker; }; template<typename Ret,typename Arg> struct SubscriberTemplate { template<typename T> SubscriberTemplate(T* _invoker, Ret (T::*mem_func)(Arg) ): bounder( new MemberFunctionBounder<T,Ret,Arg>(_invoker,mem_func)) { printf("new MemberFunctionBounder/n"); } ~SubscriberTemplate() { printf("delete MemberFunctionBounder/n"); delete bounder; bounder = 0; } SubscriberTemplate( const SubscriberTemplate<Ret,Arg>& other) : bounder(other.bounder->clone()) { printf("Copy Constructor MemberFunctionBounder/n"); } SubscriberTemplate<Ret,Arg>& operator =( const SubscriberTemplate<Ret,Arg>& other) { bounder = other.bounder->clone(); return *this; } Ret operator ()(Arg arg) { return (*bounder)(arg); } FunctionBounderBase<Ret,Arg>* bounder; }; struct EventObject { EventObject():m_handled(false){} ~EventObject(){}; bool m_handled; }; struct EventSource { typedef SubscriberTemplate<bool, EventObject*> Subscriber; typedef std::vector<Subscriber> Subscribers; void subscriberEvent(Subscriber subscriber) { mSubscribers.push_back(subscriber); } void fireEvent(EventObject* e) { bool ret = false; for( Subscribers::iterator it = mSubscribers.begin(); it != mSubscribers.end(); ++it) { Subscriber* subscriber = &(*it); ret |= (*subscriber)(e); } } Subscribers mSubscribers; }; struct Base { bool fun(EventObject* e) { printf("Base::fun(EventObject* e)/n"); return true; } }; int _tmain(int argc, _TCHAR* argv[]) { Base s; EventSource* source = new EventSource; source->subscriberEvent( EventSource::Subscriber(&s, &Base::fun)); EventObject e; source->fireEvent(&e); delete source; getchar(); return 0; }