我正在创建一种机制,接收者可以通过该机制告诉发送者每个接收者都对某种类型的消息感兴趣。在下面的示例实现中,存在一个限制,即想要接收某个基本类型的所有消息的接收器只接收显式属于该类型的消息,而不会接收派生类型的消息(例如,参见 main())。
一个潜在的解决方案是在注册特定消息时注册消息的所有祖先类型,并使用该信息正确路由消息。
还有哪些其他解决方案?
注意:实际上,我会存储 RTTI,这样就不需要每次都进行 RTTI 查找。还有其他我在这里略过/跳过的东西。我会用这个例子来简洁...
下面的示例代码:
class Sender
{
typdef std::vector<Receiver const & > Receivers;
public:
void register(Receiver const & i_recv, typeinfo const & i_type)
{
m_routingMap[i_type].push_back(i_recv);
}
void send(BaseMsg const & i_msg)
{
Receivers receivers = m_routingMap.find(typeid(i_msg));
for (Receivers::iterator receiver = receivers.begin(); receiver != receivers.end(); ++receiver) {
receiver.receive(i_msg);
}
}
private:
std::map<typeinfo const &, Receivers> m_routingMap;
};
class Receiver
{
public:
void receiver(BaseMsg const & i_msg)
{
// React to expected messages here
}
};
class BaseMsg {};
class ChildMsg : public BaseMsg {};
int main()
{
Sender sndr;
Receiver recv1;
sndr.register(recv1, typeid(BaseMsg));
Receiver recv2;
sndr.register(recv2, typeid(ChildMsg));
BaseMsg baseMsg;
sndr.send(baseMsg); // I want only recv1 to receive this message
ChildMsg childMsg;
sndr.send(childMsg); // I want both Receivers to receive this message, but only recv2 will receive it
}
更新:这是我正在解决的解决方案:
// Note: implementation is based in gleaning from
// http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.14
class BaseMsg
{
public:
typedef std::vector<TypeInfo const & > Types;
static TypeInfo const * getType()
{
TypeInfo static * ms_type = new TypeInfo(typeid(BaseMsg));
return ms_type;
}
static Types const * getAncestorTypes()
{
// The base class does not have an ancestor
// Static varible, will only be constructed once!
Types * ms_ancestorTypes = new Types();
return ms_ancestorTypes;
}
};
class ChildMsg
{
public:
static TypeInfo const * getType()
{
TypeInfo static * ms_type = new TypeInfo(typeid(ChildMsg));
return ms_type;
}
static Types const * getAncestorTypes()
{
// Add the parent type and all the parent's ancestor's types
Types const * ancestorTypes = BaseMsg::getAncestorTypes();
// Static variable, so it will only be constructed once!
Types * static ms_ancestorTypes = new Types(ancestorTypes->begin(), ancestorTypes->end());
// This push_back() will occur every time, but it's only one operation,
// so hopefully it's not a big deal!
ms_ancestorTypes->push_back(BaseMsg::getType());
return ms_ancestorTypes;
}
};
和发件人:
# Python pseudo code
class Sender:
def send(self, i_msg):
types_to_check_for = [i_msg.getType()].extend(i_msg.getAncestorTypes())
for type_ in types_to_check_for:
for receiver in _routing_list[type_]:
receiver.receive(i_msg)