2010-08-03 11 views
5

Tengo un requisito para crear algunos objetos que implementan una interfaz determinada, donde el tipo de implementación concreta que se está creando se basa en un valor Enum.¿El patrón de fábrica resolverá mi problema?

Tengo problemas cuando las diferentes implementaciones concretas requieren diferentes parámetros en tiempo de ejecución.

Este ejemplo (C#) está bien:

public enum ProductCategory 
{ 
    Modem, 
    Keyboard, 
    Monitor 
} 

public class SerialNumberValidatorFactory() 
{ 
    public ISerialNumberValidator CreateValidator(ProductCategory productCategory) 
    { 
     switch (productCategory) 
     { 
      case ProductCategory.Modem: 
       return new ModemSerialNumberValidator(); 
      case ProductCategory.Keyboard: 
       return new KeyboardSerialNumberValidator(); 
      case ProductCategory.Monitor: 
       return new MonitorSerialNumberValidator(); 
      default: 
       throw new ArgumentException("productType", string.Format("Product category not supported for serial number validation: {0}", productCategory)) 
     } 
    } 
} 

Sin embargo, ¿qué ocurre si las implementaciones concretas tienen diferentes argumentos de constructor? No puedo pasar todos los valores al método SerialNumberValidatorFactory.CreateValidator(), entonces, ¿cómo procedo?

He oído que el patrón Abstract Factory se supone que resuelve esto, pero no estoy seguro de cómo implementarlo correctamente.

+0

¿Puede en su lugar agregar los parámetros del constructor en un método de inicialización en la interfaz? Esto te dejará con un constructor sin parámetros. La definición de los parámetros del constructor significará que la persona que llama debe proporcionar los argumentos (a menos que la fábrica pueda proporcionarlos), rompiendo el punto al utilizar una interfaz, ya que la persona que llama ahora está suministrando cosas específicas para una implementación. –

+0

@ Adam, sí, había pensado en eso. Lo único que hace es vigilar la llamada a 'Initialise()'. Al menos con ctor args, son * valores * obligatorios que no puede evitar que pasen. –

+0

Siempre puede agregar una capa más de interfaces, una clase 'Settings' que contiene los argumentos para un tipo determinado. A continuación, puede exponer un 'ISettings' para cada validador que solicite la configuración y pasarlo a la fábrica de clases' CreateValidator'. Esto significa que está pasando valores escritos a otra interfaz, así que supongo que está vinculado a esa interfaz, pero incluso pasando el 'ProductType' su código ya está esperando un cierto tipo, por lo que pasar una determinada interfaz no va a doler. nunca más. –

Respuesta

2

Siempre puede crear un contenedor de Configuraciones para pasar al método CreateValidator. Comience con una base IValidatorSettings, luego cree IModemSerialNumberValidatorSettings etc., su CreateValidator podría tomar los argumentos ProductType y IValidatorSettings.

Sus clases concretas para los validadores tomarían entonces su interfaz IXXXValidatorSettings como único argumento constructor.

Además de esto, podría crear una fábrica IValidatorSettings.

Creo que la fábrica abstracta es una fábrica que crea una fábrica para manejar un conjunto determinado de tipos, no estoy seguro de si se aplicaría en su escenario.

2

Lo que está utilizando es un patrón Factory Method, lo que se debe utilizar es una fábrica abstracta

En la fábrica abstracta, se proporciona una clase de fábrica para cada aplicación concreta:

lo que el código se convierte en: (perdonar el código, pero el razonamiento es el mismo)

public class SerialNumberValidatorFactory 
{ 
    public static SerialNumberValidatorFactory newInstance(
      ProductCategory productCategory) 
    { 
     switch (productCategory) 
     { 
      case ProductCategory.Modem: 
       return new ModemValidatorFactory(); 
      .... 
     } 
    } 

    public abstract ISerialNumberValidator createValidator(); 
} 

public class ModemValidatorFactory extends SerialNumberValidatorFactory 
{ 
    public ISerialNumberValidator createValidator() 
    { 
     return new ModemSerialNumberValidator("model", "number"); 
    } 
} 

ISerialNumberValidator = SerialNumberValidatorFactory.newInstance(productCategory).createValidator() 
Cuestiones relacionadas