C++作为一门像瑞士军刀一样的编程语言很灵活很强大,可以使用它来实现其他语言有的特性。以下代码将用例子来展示一个用C++来实现事件和委托类似的功能,在我们的MiniPage类里面挂接一个Button,当有Button的点击事件发生的时候,通过委托来调用我们自己写好的回调函数。
首先, Event.h里定义我们需要的事件和委托类型
#ifndef _EVENT_H
#define _EVENT_H
#include <vector>
#include <algorithm>
// define virtual handler for event
template<class AT>class EventHandler
{
public:
virtual ~EventHandler(){}
virtual void operator()( AT& )=0;
};
// specific handler , event delegate
template< class T, class AT >
class EventDelegate : public EventHandler<AT>
{
private:
typedef T ClassType;
typedef AT ArgsType;
typedef void ( ClassType::*Handler )( AT& args );
public:
EventDelegate( ClassType* target, Handler handler )
: _target(target)
, _Handler(handler)
{
}
~EventDelegate(){}
virtual void operator()(AT& agrs )
{
( _target->*_Handler )(agrs);
}
private:
EventDelegate();
EventDelegate( const EventDelegate& );
EventDelegate& operator=( const EventDelegate& );
ClassType* <span style="white-space:pre"> </span>_target;
Handler <span style="white-space:pre"> </span>_Handler;
};
// one event <-- many handlers
template<class AT >class Event
{
private:
typedef AT AgrsType;
typedef Event< AgrsType > ThisType;
typedef EventHandler< AgrsType > HandlerType;
typedef std::vector<HandlerType*> HandlerList;
typedef typename HandlerList::iterator HandlerIterator; // typename is important !
public:
Event(){}
~Event()
{
HandlerIterator itr = mHandlerList.begin();
for( ; itr != mHandlerList.end(); ++itr )
{
delete *itr;
}
mHandlerList.clear();
}
ThisType& operator+=( EventHandler<AgrsType>* handler )
{
HandlerIterator itr;
itr = std::find( mHandlerList.begin(), mHandlerList.end(), handler );
if ( itr == mHandlerList.end() )
{
mHandlerList.push_back( handler );
}
return *this;
}
ThisType& operator-=( EventHandler<AgrsType>* handler )
{
HandlerIterator itr;
itr = std::find( mHandlerList.begin(), mHandlerList.end(), handler );
if ( itr != mHandlerList.end() )
{
mHandlerList.erase( handler );
}
return this;
}
void operator()( AgrsType& agrs )
{
HandlerIterator itr = mHandlerList.begin();
while ( itr != mHandlerList.end() )
{
(*(*itr))(agrs);
++itr;
}
}
private:
HandlerList <span style="white-space:pre"> </span>mHandlerList;
};
#endif//_EVENT_H
再来,ControlButton.h 定义用于触发事件的控件按钮
#ifndef _CONTROL_BUTTON_H
#define _CONTROL_BUTTON_H
#include "Event.h"
class ControlButton;
// agrs tell us witch obj's event occurs;
class ButtonTouchAgrs
{
public:
ButtonTouchAgrs();
ControlButton* getButton()const { return mButton; }
void setButton( ControlButton* button ) { mButton = button; }
private:
ControlButton* <span style="white-space:pre"> </span>mButton;
};
typedef Event<ButtonTouchAgrs> EventType;
class ControlButton
{
public:
ControlButton();
~ControlButton();
template< class TargetT, class AT >
void setPressEventHandler( EventDelegate<TargetT, AT>* handler )
{
mPressEvent += handler;
}
template< class TargetT, class AT >
void setReleaseEventHandler( EventDelegate<TargetT, AT>* handler )
{
mReleaseEvent += handler;
}
void doButtonCheck( int index );
private:
EventType mPressEvent; // specific event
EventType mReleaseEvent;
};
#endif //_CONTROL_BUTTON_H
ControlButton.cpp
#include "ControlButton.h"
ButtonTouchAgrs::ButtonTouchAgrs()
{
mButton = 0;
}
ControlButton::ControlButton()
{
}
ControlButton::~ControlButton()
{
}
void ControlButton::doButtonCheck( int times )
{
ButtonTouchAgrs agrs;
agrs.setButton( this );
if ( 3 == times ) // means touch event occurs when times is 3 sec
{
mPressEvent( agrs);
}
else if( 5 == times )<span style="white-space:pre"> </span>// means release event occurs when times is 5 sec
{
mReleaseEvent( agrs );
}
}
#ifndef _MINI_PAGE_H
#define _MINI_PAGE_H
#include "ControlButton.h"
class MiniPage
{
public:
MiniPage(): mButton(NULL){}
~MiniPage();
void initPage();
// define callback methods
void onButtonPress( ButtonTouchAgrs& args );
void onButtonRelease( ButtonTouchAgrs& args );
ControlButton* getButton() const { return mButton; }
private:
ControlButton*<span style="white-space:pre"> </span> mButton;
};
#endif //_MINI_PAGE_H
MiniPage.Cpp
#include "MiniPage.h"
MiniPage::~MiniPage()
{
if ( mButton )
{
delete mButton;
mButton = NULL;
}
}
void MiniPage::initPage()
{
mButton = new ControlButton;
mButton->setPressEventHandler( new EventDelegate<MiniPage, ButtonTouchAgrs>( this, &MiniPage::onButtonPress ) );
mButton->setReleaseEventHandler( new EventDelegate<MiniPage, ButtonTouchAgrs>( this, &MiniPage::onButtonRelease ) );
}
void MiniPage::onButtonPress( ButtonTouchAgrs& args )
{
printf( "button press callback method\n ");
}
void MiniPage::onButtonRelease( ButtonTouchAgrs& args )
{
printf( "button release callback method\n ");
}
最后,我们需要一个用例,来测试我们在MiniPage挂载的ControlButton在指定的时间到达后,是否会触发相应的事件,并调用在MiniPage里面定义的回调函数
main.cpp
/** created by Luo Zheng@chengdu 2014.8.16 **/
/*
this project used to simulate the Delegate & Event :
when times is 3, touch button and run the callback "onButtonPress"
when times is 5, release button and run the callback "onButtonRelease"
*/
#ifndef _MAIN_H
#define _MAIN_H
#include <time.h>
#include "MiniPage.h"
int gTime = 0;
int deltaTime = 0;
int main()
{
MiniPage* miniPage = new MiniPage;
miniPage->initPage();
gTime = time( 0 );
int temp = 0;
while( true )
{
temp = time( 0 );
if ( 1 <= temp - gTime )
{
gTime = temp;
++deltaTime;
miniPage->getButton()->doButtonCheck(deltaTime);
}
}
return 0;
}
#endif //_MAIN_H
最后的结果,说明我们定义的事件被触发,并通过委托类型调用了我们先注册的回调函数.