处理多种消息类型的设计模式 [英] Design pattern for handling multiple message types

查看:99
本文介绍了处理多种消息类型的设计模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的办公桌上有 GOF,我知道一定有某种设计模式可以解决我遇到的问题,但我想不通.

I've got the GOF sitting on my desk here and I know there must be some kind of design pattern that solves the problem I'm having, but man I can't figure it out.

为简单起见,我更改了我正在使用的一些接口的名称.

For simplicities sake, I've changed the name of some of the interfaces that I'm using.

问题来了,在线路的一侧,我有多个服务器发送不同类型的消息.在线路的另一端,我有一个客户端,它需要能够处理所有不同类型的消息.

So here's the problem, on one side of the wire, I've got multiple servers that send out different types of messages. On the other side of the wire I have a client that needs to be able to handle all the different types of messages.

所有消息都实现相同的公共接口 IMessage.我的问题是,当客户端收到一条新的 IMessage 时,它​​如何知道它收到的是什么类型的 IMessage?

All messages implement the same common interface IMessage. My problem is, when the client gets a new IMessage, how does it know what type of IMessage its received?

我以为我可以做类似以下的事情,但这感觉很糟糕.

I supposed I could do something like the following, but this just FEELS awful.

TradeMessage tMessage = newMessage as TradeMessage;
if (tMessage != null)
{
    ProcessTradeMessage(tMessage);
}

OrderMessage oMessage = newMessage as OrderMessage;
if (oMessage != null)
{
    ProcessOrderMessage(oMessage);
}

第二个想法是向 IMessage 添加一个名为 MessageTypeID 的属性,但这需要我编写如下内容,这也感觉很糟糕.

The second thought, is to add a property to IMessage called MessageTypeID, but that would require me to write something like the following, which also FEELS awful.

TradeMessage tMessage = new TradeMessage();
if (newMessage.MessageTypeID == tMessage.MessageTypeID)
{
    tMessage = newMessage as TradeMessage;
    ProcessTradeMessage(tMessage); 
}

OrderMessage oMessage = new OrderMessage();
if (newMessage.MessageTypeID == oMessage.MessageTypeID)
{
    oMessage = newMessage as OrderMessage;
    ProcessOrderMessage(oMessage);
}

我知道这个普遍问题已经被解决了一百万次,所以必须有一个更好的方法来解决一个方法的问题,该方法将接口作为参数,但需要根据实现的类进行不同的流控制那个界面.

I know this general problem has been tackled a million times, so there has to be a nicer way of solving the problem of having a method that takes an interface as a parameter, but needs different flow control based on what class has implemented that interface.

推荐答案

您可以为每种消息类型创建单独的消息处理程序,并天真地将消息传递给每个可用的处理程序,直到找到可以处理它的处理程序.类似于责任链模式:

You could create separate message handlers for each message type, and naively pass the message to each available handler until you find one that can handle it. Similar to the chain of responsibility pattern:

public interface IMessageHandler {
    bool HandleMessage( IMessage msg );
}

public class OrderMessageHandler : IMessageHandler {
    bool HandleMessage( IMessage msg ) {
       if ( !(msg is OrderMessage)) return false;

       // Handle the message and return true to indicate it was handled
       return true; 
    }
}

public class SomeOtherMessageHandler : IMessageHandler {
    bool HandleMessage( IMessage msg ) {
       if ( !(msg is SomeOtherMessage) ) return false;

       // Handle the message and return true to indicate it was handled
       return true;
    }
}

... etc ...

public class MessageProcessor {
    private List<IMessageHandler> handlers;

    public MessageProcessor() {
       handlers = new List<IMessageHandler>();
       handlers.add(new SomeOtherMessageHandler());
       handlers.add(new OrderMessageHandler());
    }

    public void ProcessMessage( IMessage msg ) {
       bool messageWasHandled
       foreach( IMessageHandler handler in handlers ) {
           if ( handler.HandleMessage(msg) ) {
               messageWasHandled = true;
               break;
           }
       }

       if ( !messageWasHandled ) {
          // Do some default processing, throw error, whatever.
       }
    }
}

您也可以将其实现为映射,将消息类名称或消息类型 ID 作为键,将适当的处理程序实例作为值.

You could also implement this as a map, with the message class name or message type id as a key and the appropriate handler instance as the value.

其他人建议让消息对象处理"自己,但这对我来说并不合适.似乎最好将消息的处理与消息本身分开.

Others have suggested having the message object "handle" itself, but that just doesn't feel right to me. Seems like it would be best to separate the handling of the message from the message itself.

我喜欢的其他一些东西:

Some other things I like about it:

  1. 您可以通过 spring 或其他方式注入消息处理程序,而不是在构造函数中创建它们,从而使其非常易于测试.

  1. You can inject the message handlers via spring or what-have-you rather than creating them in the constructor, making this very testable.

您可以通过简单地从 ProcessMessage 循环中删除中断"来引入类似主题的行为,其中您有多个处理单个消息的处理程序.

You can introduce topic-like behavior where you have multiple handlers for a single message by simply removing the "break" from the ProcessMessage loop.

通过将消息与处理程序分开,您可以在不同的目的地为相同的消息使用不同的处理程序(例如,多个 MessageProcessor 类以不同的方式处理相同的消息)

By separating the message from the handler, you can have different handlers for the same message at different destinations (e.g. multiple MessageProcessor classes that handle the same messages differently)

这篇关于处理多种消息类型的设计模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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