views:

2926

answers:

2

A program receives a list of Messages (base type). Each message in the list has to be processed according to it's type (descendant type). However, different messages need different inputs in order to be processed correctly.

What is the following technique called? (I haven't checked this code in a compiler)

abstract class MessageProcessor
{
    public static MessageProcessor GetProcessor(Message message, DataDomain data)
    {
     if (message.GetType() == typeof(FooMessage))
     {
      return new FooMessageProcessor(message, data.Name, data.Classification);

     }
     else if (message.GetType() == typeof(BarMessage))
     {
      return new BarMessageProcessor(message, data.AccountNo, data.CreditLimit);

     }
     else
      throw new SomeException("Unrecognized type");

    }

    public abstract void Process();     
}

And this one?

static class MessageProcessorFactory
{
    public static MessageProcessor GetProcessor(Message message, DataDomain data)
    {
     if (message.GetType() == typeof(FooMessage))
     {
      return new FooMessageProcessor(message, data.Name, data.Classification);

     }
     else if (message.GetType() == typeof(BarMessage))
     {
      return new BarMessageProcessor(message, data.AccountNo, data.CreditLimit);

     }
     else
      throw new SomeException("Unrecognized type");
    }
}

And what is it called if I can inject the ProcessBuilder class into a MessageProcessor (using a property or Setter) and then call Process?

What technique would be the best pattern for solving this problem?

+6  A: 

They are both examples of the factory method pattern. The only difference is that the second example has the method in its own static class.

This would be an example of the abstract factory pattern:

abstract class MessageProcessorFactory
 { public abstract MessageProcessor GetProcessor
                                     (Message message, DataDomain data);
 }

class FooMessageProcessorFactory :  MessageProcessorFactory
 { public override MessageProcessor GetProcessor
                                     (Message message, DataDomain data)
    { return new FooMessageProcessor(data.Name, data.Classification);
    }
 }

Each MessageProcessor gets its own factory class which makes use of polymorphism.

Passing a ProcessBuilder to create the process would be the strategy pattern:

class MessageProcessor
 { ProcessBuilder builder;

   public MessageProcessor(ProcessBuilder builder)
    { this.builder = builder;
    }

   public void Process()
    { builder.BuildMessage();
      builder.BuildProcess();
      builder.Process();
    }
 }

var mp = new MessageProcessor(new FooProcessBuilder());

The simplest solution would be to encapsulate a factory method:

static void Process(Message msg, DataDomain data)
 { var p = getProcessor(msg.GetType());
   p.Process(msg, data);
 }

If it's a small known number of types, you can use the series of type checks:

private static MessageProcessor getProcessor(Type msgType)
 { return   (msgType == typeof(FooMessage)) ? new FooMessageProcessor()
          : (msgType == typeof(BarMessage)) ? new BarMessageProcessor()
          :                                   new DefaultMessageProcessor();
 }

Otherwise use a dictionary:

Dictionary<Type,MessageProcessor> processors;    

private static MessageProcessor getProcessor(Type msgType) 
 { return processors[msgType];
 }
Mark Cidade
I would do something like that, but I just used the DataDomain object as an example.In our application, there is no type that encapsulates all the input values, and in some cases it would mean passing a parameter to a method that doesn't need it.
ilitirit
For this example, you'd have to consider the trade-off between a complex design for accounting for different input parameters and a simpler design that may result in unused method arguments. If the variation isn't fixed or small, then go with a more complex design or punt and use a generic object
Mark Cidade
Worse Indentation Style Ever! :)
Gili
It's my own unique style but feel free to re-format it!
Mark Cidade
+1  A: 

In my understanding factory method defnies the abstract type of class with which to work with but delegates the creation of the concrete type to the succeeding/implementing classes. Abstract factory would define an interface for a manufactorer of a set of corresponding classes. A builder works simply to build an object step by step giving some control to the calling instance.

DaSteph