您的位置:首页 > 其它

QuteCom手记:使用Event类实现观察者模式

2011-07-05 23:02 465 查看
Event类的定义在qutecom\libs\owutil\util\event.h
/**
* Connects a slot to this signal (=event).
*
* Provides unicity when connecting a slot to a signal.
* Two identical slots cannot be connected, only one will be:
* this method checks first if the same slot was not connected already.
*
* @param slot callback function
* @return connection object
*/
template<typename Slot>
boost::signals::connection operator+=(const Slot & slot) {
boost::signals::connection c;
if (!alreadyConnected(slot)) {
//The slot is not connected to the signal
c = this->connect(slot);
SlotConnection sc;
sc.connection = c;
sc.slot = slot;
_slotList.push_back(sc);
}
//The slot is already connected to the signal
return c;
}

/**
* Connects a signal to another signal (=event).
*
* Does not check if the signal is already connected, does not
* provide unicity connection.
*
* @param event signal to connect
* @return connection object
*/
boost::signals::connection operator+=(const Event & event) {
return this->connect(event);
}

/**
* Disconnects a slot from a signal (=event).
*
* Slot comparison does not always work properly,
* check http://boost.org/doc/html/function/faq.html#id2699084 *
* @param slot callback function to disconnect from the signal
*/
template<typename Slot>
void operator-=(const Slot & slot) {
typename SlotList::iterator it;
for (it = _slotList.begin(); it != _slotList.end(); it++) {
if ((*it).slot == slot)
break;
}
if (it != _slotList.end()) {
(*it).connection.disconnect();
_slotList.erase(it);
}
}

Event继承了 boost::signal,重载了-=和+=运算符。分别对应boost::signal的disconncet和connect。
Event在PhoneCall类中的使用:
qutecom\qutecom\src\model\phonecall\phonecall.h
/**
* The state of the PhoneCall has changed.
*
* @param sender this class
* @param status new status
*/
Event<void (PhoneCall & sender, EnumPhoneCallState::PhoneCallState status)> stateChangedEvent;

/**
* A video frame has been received from the network.
*
* @param sender this class
* @param remoteVideoFrame remote video frame
* @param localVideoFrame local video frame from the webcam
*/
Event<void (PhoneCall & sender, piximage * remoteVideoFrame, piximage * localVideoFrame)> videoFrameReceivedEvent;
stateChangedEvent的声明说明函数对象的原型为void (PhoneCall & sender, EnumPhoneCallState::PhoneCallState status),无返回值,第一个参数为PhoneCall对象的引用,第二个参数为一个状态码。
stateChangedEvent事件的“事件处理函数”设置:

void CPhoneCall::initPresentationThreadSafe() {
_pPhoneCall = PFactory::getFactory().createPresentationPhoneCall(*this);

_phoneCall.stateChangedEvent += boost::bind(&CPhoneCall::stateChangedEventHandler, this, _1, _2);
_phoneCall.videoFrameReceivedEvent += boost::bind(&CPhoneCall::videoFrameReceivedEventHandler, this, _1, _2, _3);
}
注意boost::bind的第二参数为this指针而不能为对象,这是因为CPhoneCall的实例是不可复制对象。见CPhoneCall的声明。

stateChangedEvent事件的触发:
void PhoneCall::setState(EnumPhoneCallState::PhoneCallState state) {
LOG_DEBUG("PhoneCallState=" + String::fromNumber(state));

for (unsigned i = 0; i < _phoneCallStateList.size(); i++) {
PhoneCallState * callState = _phoneCallStateList[i];
if (callState->getCode() == state) {
if (_state->getCode() != callState->getCode()) {
_state = callState;
//省略......
LOG_DEBUG("call state changed callId=" + String::fromNumber(_callId) +
" state=" + EnumPhoneCallState::toString(_state->getCode()));
applyState(state);
stateChangedEvent(*this, state);
return;
}
}
}

//LOG_FATAL("unknown PhoneCallState=" + String::fromNumber(state));
}
当模型PhoneCall的实例发生状态改变时,将触发stateChangedEvent。第一参数为PhoneCall实例引用,第二参数为状态代码。由此将调用对应CPhoneCall对应实例的stateChangedEventHandler函数,并将两个参数传递给它。
注意他们在同一上下文中执行。
Event用这种方法实现了观察者模式,CPhoneCall是观察者,PhoneCall是被观察模型。
还有CPhoneLine和PhoneLine也是如此。

关于boost::bind的文章请见:
http://blog.csdn.net/Solstice/article/details/3066268
http://www.cppblog.com/shanoa/archive/2009/06/15/87746.aspx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: