2010-08-03 17 views
5

È necessario creare alcuni oggetti che implementano un'interfaccia specifica, in cui il tipo di implementazione concreta che si sta creando è basato su un valore Enum.Il modello di fabbrica risolverà il mio problema?

Mi trovo nei guai quando le diverse implementazioni concrete richiedono parametri diversi in fase di esecuzione.

Questo esempio (C#) va bene:

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

Tuttavia, cosa succede se le implementazioni concrete hanno differenti argomenti del costruttore? Non riesco a passare tutti i valori al metodo , quindi come procedo?

Ho sentito che lo schema Abstract Factory dovrebbe risolvere questo problema, ma non sono sicuro di come implementarlo correttamente.

+0

È possibile invece aggregare i parametri del costruttore in un metodo di inizializzazione sull'interfaccia? Questo ti lascerà con un costruttore senza parametri. La definizione dei parametri del costruttore implicherà che il chiamante debba fornire gli argomenti (a meno che la fabbrica non li possa fornire), rompendo il punto nell'utilizzo di un'interfaccia poiché il chiamante ora fornisce elementi specifici per un'implementazione. –

+0

@Adam sì, ci avevo pensato. L'unica cosa è quindi controllare la chiamata a 'Initialise()'. Almeno con Ctor Arg, sono * i valori richiesti * che non è possibile evitare di passare. –

+0

È sempre possibile aggiungere un ulteriore livello di interfacce: una classe 'Settings' che contiene gli argomenti per un determinato tipo. È quindi possibile esporre un 'ISettings' per ogni validatore che richiede le impostazioni e passare questo alla classe factory' CreateValidator'. Ciò significa che stai passando valori digitati a un'altra interfaccia, quindi suppongo che tu sia legato a quell'interfaccia, ma anche passando il 'ProductType' il tuo codice è già in attesa di un certo tipo, quindi passare una determinata interfaccia non farà male più. –

risposta

2

È sempre possibile creare un contenitore di impostazioni per passare al metodo CreateValidator. Inizia con una base IValidatorSettings, quindi crea IModemSerialNumberValidatorSettings ecc. Il tuo CreateValidator potrebbe quindi utilizzare gli argomenti ProductType e IValidatorSettings.

Le vostre classi concrete per i validatori dovrebbero quindi utilizzare l'interfaccia IXXXValidatorSettings come unico argomento del costruttore.

Inoltre, è possibile creare uno stabilimento IValidatorSettings.

Penso che la fabbrica astratta sia una fabbrica che crea una fabbrica per gestire un determinato insieme di tipi - non è sicuro se si applicherebbe nel tuo scenario.

2

Cosa si sta utilizzando è un modello Factory Method, ciò che si dovrebbe utilizzare è una Fabbrica astratta

In fabbrica astratto, si fornisce una classe di fabbrica per ogni implementazione concreta:

Così il codice diventa: (perdonare il codice, ma la logica è la stessa)

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() 
Problemi correlati