2008-10-08 41 views
12

Un programa recibe una lista de mensajes (tipo de base). Cada mensaje en la lista debe ser procesado de acuerdo a su tipo (tipo de descendiente). Sin embargo, diferentes mensajes necesitan diferentes entradas para ser procesados ​​correctamente.¿Cuáles son las diferencias entre los patrones Builder, Factory Method y Abstract Factory?

¿Cómo se llama la siguiente técnica? (No he comprobado este código en un compilador)

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

¿Y este?

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

Y ¿cómo se llama si puedo inyectar la clase ProcessBuilder en un MessageProcessor (usando una propiedad o Setter) y luego llamar Proceso?

¿Qué técnica sería el mejor patrón para resolver este problema?

Respuesta

10

Ambos son ejemplos del patrón de método de fábrica. La única diferencia es que el segundo ejemplo tiene el método en su propia clase estática.

Este sería un ejemplo del patrón defábrica de resumen:

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

Cada MessageProcessor obtiene su propia clase de fábrica que hace uso de polimorfismo.

Pasar un ProcessBuilder para crear el proceso sería el estrategia patrón:

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

La solución más sencilla sería la de encapsular un método de fábrica:

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

Si se trata de una pequeña cantidad conocida de tipos, puede usar la serie de verificaciones de tipo:

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

De lo contrario usar un diccionario:

Dictionary<Type,MessageProcessor> processors;  

private static MessageProcessor getProcessor(Type msgType) 
{ return processors[msgType]; 
} 
+0

Haría algo así, pero acabo de utilizar el objeto DataDomain como ejemplo. En nuestra aplicación, no hay ningún tipo que encapsule todos los valores de entrada, y en algunos casos significaría pasar un parámetro a un método que no lo necesita – ilitirit

+0

Para este ejemplo, tendría que considerar la compensación entre un diseño complejo para tener en cuenta los diferentes parámetros de entrada y un diseño más simple que puede dar como resultado argumentos de método no utilizados. Si la variación no es fija o pequeña, vaya con un diseño más complejo o punt y use un objeto genérico –

+7

Peor estilo de sangría ¡Nunca! :) – Gili

2

En mi método de fábrica comprensión defnies el tipo abstracto de la clase con la que trabajar con los delegados, pero la creación del tipo concreto de las clases sucesivas/ejecución. La fábrica abstracta definiría una interfaz para un fabricante de un conjunto de clases correspondientes. Un constructor funciona simplemente para construir un objeto paso a paso dando cierto control a la instancia de llamada.

Cuestiones relacionadas