views:

519

answers:

8

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.

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);
}

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.

+7  A: 

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

Nicky De Maeyer
I kind of assumed that his ProcessXMessage() function hinged on code outside of his object, so his object could not internally process itself.
JustLoren
As I understand the problem, the message might not have any behavior associated with it. So I think a separate message processor with that behavior *overloaded* would be the best solution.
bruno conde
@bruno conde: Much like Vincent Ramdhanie's post - I agree, this is probably the best overall implementation.
JustLoren
This MessageProcessor addition is a good alternative. +1
bruno conde
If overloading isn't working for you, you can always pass the Processor into the IMessage.process() method and then have it do an explicit callback to the appropriate method on the Processor using a double-dispatch technique.
Trevor Tippins
You're correct JustLoren, the messages can not process themselves. The processing of the message depends on the client that receives them. The message might be written to a database, displayed on the screen, or simply stored in a local cache.
Jonathan Beerhalter
+1  A: 

Add a ProcessMessage() method to the iMessage interface and let the concrete message polymorphically decide the right way to process themselves.

Your code then becomes

newMessage.ProcessMessage();

Here is a good article on using polymorphism instead of conditionals.

Ryan Michela
+1  A: 

In a similar scenario I have a server which receives lots of different messages from multiple clients.

All messages are sent serialized and start with an identifier of message type. I then have a switch statement looking at the identifier. The messages are then deserialized (to very differing objects) and processed as appropriate.

A similar thing could be done by passing objects which implement an interface which includes a way of indicating message type.

public void ProcessMessage(IMessage msg)
{
    switch(msg.GetMsgType())  // GetMsgType() is defined in IMessage
    {
        case MessageTypes.Order:
            ProcessOrder(msg as OrderMessage);  // Or some other processing of order message
            break;
        case MessageTypes.Trade:
            ProcessTrade(msg as TradeMessage); //  Or some other processing of trade message
        break;
        ...
    }
}
Matt Lacey
+3  A: 

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();
Vincent Ramdhanie
+3  A: 

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 {
    bool HandleMessage( IMessage msg ) {
       if ( !msg is OrderMessage) return false;

       // Handle the message.
    }
}

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

       // Handle the message.
    }
}

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

Eric Petroelje
+1 I think this is a good idea.
Brian Gideon
All the solutions were great, but this one fit the needs of this application best. a TradeMessage would not be processed the same by all applications, so it didn't make sense to put the processing logic into the TradeMessage object.
Jonathan Beerhalter
+1  A: 

You might want to take a look through Enterprise Integration Patterns by Gregor Hohpe and Bobby Woolf. It has a good catalog of patterns for message processing.

Mike Two
+1  A: 

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?

Hrvoje
A: 

A dispatching pattern might work well.

public static class MessageDispatcher
{
  private static readonly IMessageHandler s_DefaultHandler =
      new DefaultMessageHandler();
  private static readonly Dictionary<Type, IMessageHandler> s_Handlers =
      new Dictionary<Type, IMessageHandler>();

  static MessageDispatcher()
  {
    // Register a bunch of handlers.
    s_Handlers.Add(typeof(OrderMessage), new OrderMessageHandler());
    s_Handlers.Add(typeof(TradeMessage), new TradeMessageHandler());
  }

  public void Dispatch(IMessage msg)
  {
    Type key = msg.GetType();
    if (s_Handlers.ContainsKey(key))
    {
      // We found a specific handler! :)
      s_Handlers[key].Process(msg);
    }
    else
    {
      // We will have to resort to the default handler. :(
      s_DefaultHandler.Process(msg);
    }
  }
}

public interface IMessageHandler
{
  void Process(IMessage msg);
}

public class OrderMessageHandler : IMessageHandler
{
}

public class TradeMessageHandler : IMessageHandler
{
}

There are all kinds of variations to this theme. They will all have a dispatcher object that contains many different handlers. You should consider a default handler in case the dispatcher cannot find a specific handler. There is a lot of freedom in how you choose to dispatch the messages to the appropriate handlers. I just happen to dispatch based on type, but you could make it arbitrarily more complex. Maybe the dispatcher could examine the contents of the message to discover the best handler. Maybe the message carries with it a key that identifies a preferred handler. I don't know. There are a lot of possibilities here.

Brian Gideon
I like this idea. But there are for 2 things I don't love about the implementation: First, if a handler is registered for type **A** using _ContainsKey(Type)_ will fail for objects of any class _derived_ from **A**. Second, a Dictionary only allows one handler per type of message.
NVRAM
@NVRAM: Very good points.
Brian Gideon