Design pattern for handling multiple message types

前端 未结 10 1044
甜味超标
甜味超标 2020-11-28 03:13

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.

F

相关标签:
10条回答
  • 2020-11-28 04:02

    For my little messaging framework inside Silverlight app i'm using Mediator pattern. It's some kind of messaging bus/broker, to which objects are subscribing for specific type or types of message. Then this Mediator object (broker/bus) is deciding who will receive what kind of messages.
    Someting like:

    SubscribeFor<ChatMessage>().If(x=>x.SomeProp==true).Deliver(MyMethod);
    

    Sample methods that are called:

    void MyMethod(ChatMessage msg) , or
    void MyMethod(BaseBessage msg)
    

    or publishing (broadcasting) of messages:

    Publish(new ChatMessage());
    

    BaseMessage is abstract class, which all my messages inherits, and have just reference to sender and some unique Guid.

    I took starting point for building my messaging framework from MVVM Light Toolkit, you can take a look at theirs source code, it's not complicated!

    If you whish, I can put c# code for this somewhere?

    0 讨论(0)
  • 2020-11-28 04:10

    One option is to have the messages come with their own handlers. That is, create an Interface called IMessageProcessor that specifies a method processMessage(IMessage). Next define concrete class that implements IMessageProcessor for each type of message.

    Each IMessage class will then define its own Processor.

    When you receieve a message object you will do something like this:

    message.processor.processMessage();
    
    0 讨论(0)
  • 2020-11-28 04:15

    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.
           }
        }
    }
    

    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. You can inject the message handlers via spring or what-have-you rather than creating them in the constructor, making this very testable.

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

    3. 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)

    0 讨论(0)
  • 2020-11-28 04:16

    A couple of solutions are applicable for this, first is best solution, last is least best. All examples are pseudocode:

    1st, and best solution

    Vincent Ramdhanie introduced the actual correct pattern to solve this problem, which is called the strategy pattern.

    This pattern creates a separate 'processor', in this case to process the messages accordingly.

    But I'm pretty sure a good explanation is given in your book by the GOF :)

    2nd

    As commented, the message may not be able to process itself, it is still usefull to create an interface for the message, or a base class, so you can make a general processing function for a message, and overload it for more specific ones.

    overloading is in any case better then creating a different method for every type of message...

    public class Message {}
    public class TradeMessage extends Message {}
    
    public class MessageProcessor {
        public function process(Message msg) {
            //logic
        }
    
        public function process(TradeMessage msg) {
            //logic
        }
    }
    

    3rd

    If your message could process itself you could write an interface, since your process method depends on what message you got, it seems easier to put it inside the message class...

    public interface IMessage
    {
        public function process(){}
    }
    

    you then implement this in all your message classes and proccess them:

    list = List<IMessage>();
    foreach (IMessage message in list) {
        message.process();
    }
    

    in your list you can store any class that implements that interface...

    0 讨论(0)
提交回复
热议问题