技巧:回调的优雅写法
设想这样一个情景,在一个函数中,你需要去回调listener中的方法,在return前通知监听者。但这个函数的逻辑分支比较多,而且可能有多个分支都需要通知listener。
示例:
void event::notify() {
int32_t res;
if (con1) {
_listener->update(res);
return;
} else if (con2) {
return;
}
// do some things. fill into res
if (con3) {
// do some things. modify res
_listener->update(res);
return;
} else if (con4) {
// do some things. modify res
_listener->update(res);
return;
}
return;
}
可以看到 _listener->update() 出现多次。这是很不优雅的写法,而且维护起来也比较困难。
提供一个更加优雅的写法:
void event::notify() {
int32_t res;
struct final_callback {
final_callback(event* this, const int32_t& param)
: _this(this), _param(param){};
~finnal_callback() {
_this->_listener->update(_param);
}
event* _this;
const int32_t& _param;
} _final_callback(this, res);
if (con1) {
return;
} else if (con2) {
return;
}
// do some things. fill into res
if (con3) {
// do some things. modify res
return;
} else if (con4) {
// do some things. modify res
return;
}
return;
}
利用了RAII优雅地解决了return前的回调问题。
但这个方案存在一个很大的问题:示例代码中最后一个return是不需要回调的,但我们的“优雅写法”中,仍然产生了回调行为。
为了解决这个问题,可以加一个标记非法的标志位,listener在update中自行判断即可。