2009-05-13 24 views
7

Diciamo che ho una classe astratta Drink e un metodo factory che sceglie il tipo di Drink (Wine, Beer, ecc.) Da creare in fase di esecuzione.Passare argomenti a una sottoclasse specifica, tramite un metodo factory

Ogni Drink necessita di alcuni argomenti per inizializzarsi correttamente. Alcuni di questi sono comuni a tutte le bevande; per esempio, potrebbero tutti richiedere un argomento DrinkConfig.

Ma ogni bevanda può avere anche i suoi requisiti specifici. Forse Wine ha bisogno di un oggetto helper Sommelier per inizializzarsi. La birra non ha bisogno di questo, ma potrebbe aver bisogno dei suoi oggetti ausiliari.

Quindi, cosa devo passare al metodo di fabbrica? Quando lo chiamo, ho a disposizione tutti gli oggetti helper, quindi posso passarli tutti in fabbrica. Ma questo potrebbe finire per essere un sacco di argomenti. C'è un modo migliore per progettare questo?

MODIFICA: Supponiamo che non sia possibile creare gli oggetti helper in fabbrica; sono disponibili solo dal chiamante.

risposta

4

Vorrei creare diversi metodi di sovraccarico nella classe di fabbrica.

public class DrinkFactory { 

    public static Drink CreateBeer(DrinkConfig config, string hops) { 
     return new Beer(config, hops); 
    } 

    public static Drink CreateWine(DrinkConfig config, string grapes, int temperature) { 
     return new Wine(config, grapes, temperature); 
    } 
} 

Edit:

Se è desiderato di avere solo un singolo metodo nella classe di fabbrica un'implementazione alternativa sarebbe:

public enum DrinksEnum { 
    Beer, 
    Wine 
} 

public class DrinkFactory { 

    public static Drink CreateDrink(DrinksEnum drinkType, DrinkConfig config) { 
     switch(drinkType) { 
      case DrinksEnum.Beer: 
       return new Beer(config); 
      case DrinksEnum.Wine: 
       return new Wine(config); 
      default: 
       throw new ApplicationException("Drink type not recognised."); 
     } 
    } 
} 
+0

Le firme vanno bene. Il problema è come passare argomenti a Factory :: CreateDrink() (o come si chiama). – dirkgently

+0

Se si desidera avere un metodo CreateDrink in fabbrica, è possibile utilizzare un parametro enum per specificare il tipo di bevanda desiderato. Non credo che o l'approccio sopra sia conforme al modello di fabbrica GoF, dove gli oggetti vengono creati nella classe Drink (ho bisogno di controllare il mio libro stasera), ma lo trovo molto più pragmatico e mantiene comunque il vantaggio principale di centralizzazione della creazione di oggetti per le gerarchie di sottoclassi. – sipwiz

+0

Dopo aver controllato il mio libro sui disegni di GoF, sono felice che l'esempio che ho fornito sopra sia quanto vicino a come usi una fabbrica come parte del modello di progettazione di Abstract Factory. Per conformarsi completamente ci dovrebbe essere una classe di fabbrica astratta che DrinkFactory eredita da, ma per casi semplici come questo normalmente la lascio fuori. Sarebbe stato abbastanza facile rifondere DrinkFactory se fosse necessario un altro stabilimento di produzione di calcestruzzo. – sipwiz

0

sono tentato di fornire una soluzione ingenua in cui il vostro gli ingredienti sono derivati ​​da una classe base 'DrinkIngredients'. Dovrai abbinare la sottoclasse da utilizzare per una bevanda particolare.

A quanto pare, si potrebbe essere tentati di creare un altro stabilimento per gli ingredienti, ma questo porterebbe a un problema di gallina e uova.

0

Generalmente, esiste un metodo di fabbrica per nascondere questi dettagli. Una domanda importante è da dove proviene il Sommelier - se tutti questi altri aiutanti sono singleton o possono essere acquisiti da una fonte conosciuta, quindi istanziare la fabbrica delle informazioni necessarie per andare a cercarli, in modo che il tuo codice chiamante non abbia bisogno preoccuparsi di questo

Inoltre, in molti casi, verrà utilizzato un framework come Spring per consentire di descrivere queste relazioni in un file di configurazione anziché in codice.

Se è necessario passare gli helper in fase di esecuzione dal codice chiamante, suggerisco di leggere il documento "Arguments and Results" (http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.50.7565) che descrive un modello comune per il marshalling di argomenti complessi. Essenzialmente, dovresti creare una raccolta intermedia dei parametri necessari e passarla alla fabbrica.

2

Il metodo factory dovrebbe astrarre i dettagli su come creare valori. Quindi non dovresti passare gli oggetti helper al metodo factory, il metodo factory dovrebbe creare l'oggetto helper di cui ha bisogno e passarlo al costruttore appropriato.

0

In casi come questo, di solito guardo ad altre soluzioni invece di passare le variabili.

Ad esempio, nel tuo caso - WineFactory che necessitano di un sommelier, in modo che possa costruire il appropriata Vino -

Questo è un caso grande utilità per l'iniezione runtime dipendenza. Un framework per l'iniezione di dipendenza di qualche forma renderebbe questo lavoro molto semplice, comprensibile e giusto senza aver bisogno di far passare tutte queste proprietà.

1

Una Fabbrica dovrebbe creare oggetti molto simili in primo luogo. Ciò significa che anche se tutti questi oggetti sono bevande, il metodo di produzione potrebbe non essere appropriato perché ogni bevanda è semplicemente molto diversa da un'altra.

Con ciò detto, è possibile passare una lista di oggetti di dimensioni pari al numero di proprietà che si desidera impostare. Ogni oggetto rappresenterebbe quindi il valore che si desidera impostare nel costruttore dell'oggetto appropriato, nell'ordine in cui si desidera impostare queste variabili. Lo svantaggio di questo è che devi formattare una lista al di fuori della fabbrica prima di effettuare la chiamata, il che è alquanto maldestro.

0

Questo sembra un caso perfetto per il modello Builder. Utilizzare lo schema Factory per la creazione di oggetti simili e il modello Builder per la costruzione di oggetti complessi e dissimili. Cercando di utilizzare il modello Factory per questo problema, molti costruttori di inizializzazione diversi (con numeri/tipi diversi di parametri) per i diversi oggetti.

Problemi correlati