避免在消息传递中向下转发的设计模式 [英] Design pattern to avoid downcasting in message passing

查看:154
本文介绍了避免在消息传递中向下转发的设计模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基类 MessageHandler 有派生类。他们想传递消息给对方。消息可以是不同的类,但可以使其共享基类。每个 MessageHandler 如何避免对接收到的消息进行向下转换?是不是有可能做一些事情,具有模板参数化在MessageHandler上的虚拟 receiveMessage 函数的效果?

Base class MessageHandler has derived classes. They would like to pass messages to each other. Messages could be of different classes, but can be made to share a base class. How can each MessageHandler avoid downcasting a received message? Is it somehow possible to do something that has the effect of template-parametrizing the virtual receiveMessage function on MessageHandler?

基本上,我试图替换下面的代码不下降,并希望是一个编译时间的东西:

Essentially, I'm trying to replace the following code with something that does not downcast, and is hopefully a compile-time thing:

// ...
virtual void MessageHandler::receiveMessage(Message &msg) = 0;
// ...

// to receive a message
void DerivedMessageHandler::receiveMessage(Message& msg)
{
    switch (msg.MsgType()) // enum
    {
        case Message::MessageType::A:
            MessageA& = dynamic_cast<MessageA&>(msg);
            break;

        case Message::MessageType::B:
            MessageB& = dynamic_cast<MessageB&>(msg);
            break;
        default:
            // don't process unknown messages
            break;
    }
}

// to send a message
list<MessageHandler> mhList;
// populate list
for (MessageHandler& mh : mhList)
{
    mh.receiveMessage(msg);
}



我知道我不能这样做,

I know I can't do this, but something like

template <typename M>
void MessageHandler::receiveMessage(M& msg) {}

c $ c> DerivedMessageHandler 专注于 M ?什么是设计模式,干净地让每个处理程序在其支持的消息对象上工作?

And have each DerivedMessageHandler specialize on M? What would be a design pattern that cleanly lets each handler work on their supported message objects?

推荐答案

这是很容易做到的。通常有两种选择:

This is pretty easy to do. There are generally two alternatives:

不是传递派生类,类型,消息可以是。这些类型不需要彼此派生。将这些类型包含在 boost :: variant 中: / p>

Instead of passing a derived class, simply enumerate the possible types that a message could be. These types need not be derived from one another. Wrap those types in a boost::variant:

typedef boost::variant<MessageData1, MessageData2, MessageData3, ...> MessageData;

注意,这意味着可能的消息数据类型必须是可枚举的。 Boost.Variant的访问方法使得能够容易地处理这些类型的对象,而不知道它存储哪些类型。

Note that this means that the possible message data types must be enumerable. Boost.Variant's visitation methods make it easy to work with objects of these types without knowing exactly which type it stores.

只需传递带有 boost :: any 的任何东西:

Simply pass anything with a boost::any:

void MessageHandler::receiveMessage(const boost::any &msg)
{
  const MessageType1 *pMsg = boost::any_cast<MessageType1>(&msg);
  if(!pMsg)
    //Cannot process
    return;

  //Process message.
}

boost :: any 就像一个类型安全的 void * 。它记住被放入其中的确切类型,并且任何试图将它投射到其他以外的东西将失败。 boost :: any 可以存储任何东西,因此名称。

boost::any is like a type-safe void*. It remembers the exact type that was put into it, and any attempt to cast it to something other than what is stored in it will fail. boost::any can store anything, hence the name.

它也有值语义,因此它可以如同其内容一样复制。

It also has value semantics, so it can be copied like its contents.

这篇关于避免在消息传递中向下转发的设计模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆