通用编程能力训练:发布-订阅模式
2009-05-13 00:48
381 查看
发布-订阅模式核心代码练习:
实现以下参与者:
EventObject
事件对象,用于参数传递
EventSource
事件源,用于触发事件
SubscriberTemplate
订阅器模板,保存客户代码
特殊需求:采用模板实现可定制的客户代码。
心得:
1、为了在 SubscriberTemplate 层面使 invoker 的类型无关,使用了 模板构造函数 和 MemberFunctionBounder ,将 invoker 的类型确定时机推到了 MemberFunctionBounder 层。
2、为了能在 SubscriberTemplate 调用客户代码,将 invoker 无关的接口抽象,形成 FunctionBounderBase 层。
3、为了保证 SubscriberTemplate 在赋值、拷贝、删除的时候对 bounder 对象的管理, 在 FunctionBounderBase 层添加了 clone 方法。
扩展:
1、支持非成员函数的客户代码。
2、支持非返回值的客户代码。
3、完善事件触发机制,添加注册、查找事件的功能。
实现以下参与者:
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; }
相关文章推荐
- js事件编程的发布/订阅模式(一对一关系)
- js发布——订阅模式的通用实现及取消订阅
- 通用编程能力训练:template
- 通用编程能力训练 -- 设计心得:分步载入的改造(包含异步IO练习)
- 通用编程能力训练:Memory Track(2012-01-29 19:02)
- Spring整合activeMq(二):发布订阅模式
- redis 消息队列 发布、订阅模式
- ActiveMQ的发布订阅模式
- 窗体传值发布订阅模式(委托版)
- NetMQ 发布订阅模式 Publisher-Subscriber
- 15天玩转redis —— 第九篇 发布/订阅模式
- 观察者模式和发布/订阅模式
- redis订阅发布模式
- 理解javascript的设计模式之发布订阅模式
- js设计模式之代理模式以及订阅发布模式
- 发布-订阅模式
- 发布-订阅消息模式
- redis的发布订阅模式pubsub
- js全局的发布——订阅模式
- RabbitMQ下的生产消费者模式与订阅发布模式