2010-04-23 8 views
8

Questo mi ha infastidito per un po ', e non ho nessun indizio se questo è un mito.mito modello di fabbrica

Sembra che uno schema di fabbrica possa alleviare il dolore di aggiungere una dipendenza per una classe.

Per esempio, in un libro, è qualcosa di simile

Si supponga di avere una classe denominata Order. Inizialmente non dipendeva da nulla. Quindi non ti sei preoccupato di usare una fabbrica per creare oggetti Ordine e hai semplicemente usato semplicemente nuovo per creare un'istanza degli oggetti. Tuttavia, ora è necessario che l'Ordine sia creato in associazione con un Cliente. Ci sono milioni di posti che devi cambiare per aggiungere questo parametro extra. Se solo tu avessi definito una fabbrica per la classe dell'Ordine, avresti incontrato il nuovo requisito senza lo stesso dolore.

In che modo non è la stessa pena aggiungere un parametro aggiuntivo al costruttore? Voglio dire che avresti ancora bisogno di fornire un argomento in più per la fabbrica e che è anche usato da milioni di posti, giusto?

+0

Ci sono milioni (se non miliardi di libri) là fuori. Non tutti sono corretti. Non dare nulla per scontato solo perché qualcuno lo ha scritto in un libro. – kazanaki

risposta

5

Se l'utente è noto solo al momento, l'ordine viene creato, è possibile implementare una funzione getCurrentUser() che viene chiamata dalla fabbrica.
Se ciò è possibile, la funzione di fabbrica ovviamente vince. In caso contrario, non vi è alcun guadagno.

Se, in passato, non sapevi che ci sarebbe stato bisogno di un cliente, probabilmente non sapresti nemmeno se sia possibile implementare una funzione getCurrentUser(). Le possibilità di pagamento del metodo di produzione potrebbero non essere molto buone ma non sempre uguali a 0.

+0

Penso che sia esattamente quello che sto cercando. – leiz

+1

esattamente. se hai bisogno di nuove informazioni, la tua fabbrica non ti aiuterà. se hai o puoi ottenere le informazioni di cui hai bisogno, la fabbrica ti aiuta a evitare le modifiche ovunque. –

1

Dite la fabbrica della nuova dipendenza, e lasciare inserirlo per voi. La chiamata di metodo alla fabbrica dovrebbe rimanere invariata.

+0

Se devo dire alla fabbrica della nuova dipendenza, allora come è diverso dall'usare il vecchio "nuovo" e aggiungere un argomento in più? La nuova dipendenza non è un oggetto fisso. – leiz

+0

Dite alla fabbrica una volta, non ovunque nel codice in cui chiamate la fabbrica per creare l'oggetto. –

2

No, perché la dipendenza per la fabbrica deve essere iniettata tramite il costruttore delle fabbriche, e si sta costruendo la fabbrica in un unico posto, ma passandolo come dipendenza a tutto ciò che ha bisogno di creare un ordine. Le cose che stanno ricevendo ordini dalla fabbrica stanno ancora chiamando lo stesso metodo, CreateOrder() o qualsiasi altra cosa, e così il codice è invariato.

Le dipendenze dovrebbero essere collegati in un unico luogo, il composition root, e che dovrebbe essere l'unico luogo che ha bisogno di cambiare, di aggiungere la nuova dipendenza alla fabbrica

+0

Non capisco. Diciamo che voglio creare un oggetto Ordine, dipende da un oggetto cliente, ma il cliente è conosciuto solo al momento della creazione dell'oggetto Ordine. Come suppongo di installare la fabbrica nelle prime fasi? – leiz

+0

Questo non aggiunge una dipendenza alla classe, vero? questo sta aggiungendo nuove informazioni. Se hai bisogno di nuove informazioni per poter creare il tuo ordine, dovrai aggiungerlo ovunque. Ma se è possibile determinare il cliente dalle informazioni esistenti, se la classe Order ha accesso a un'implementazione ICustomerResolver, se si è utilizzato uno stabilimento è possibile iniettare ICustomerResolver in fabbrica e il codice di creazione dell'ordine rimarrà invariato. Senza la fabbrica è necessario iniettare ICustomerResolver in ogni costruttore di ordini. –

+0

Mi dispiace, ma ho pensato che una nuova informazione fosse una dipendenza. E tutti i progetti dovevano già sapere che ci sarebbe stata una nuova esigenza del cliente. Questo è il motivo per cui sto dicendo che il libro è fuorviante. – leiz

1

The factory pattern può alleviare il dolore di aggiunta una dipendenza, perché una fabbrica può contenere stato e, infatti, può incapsulare più dipendenze (ad esempio, invece di fornire tre dipendenze, tutti bisogno di invocare il costruttore di qualche oggetto, è ora forniscono solo un oggetto di fabbrica di singolo, dove la fabbrica contiene quelli tre oggetti che devono essere forniti al costruttore).

per fare un esempio, confrontare:

void DoIt(const DependencyA& a, const DependencyB& b) { 
    // NOTE: "x" is a contrived additional variable that we add here to 
    // justify why we didn't just pass DependencyC directly. 
    int x = ComputeX(); 
    std::unique_ptr<DependencyC> dependency_c(new DependencyC(a, b, x)); 
    dependency_c->DoStuff(); 
} 

E:

void DoIt(const DependencyCFactory& factory) { 
    int x = ComputeX(); 
    std::unique_ptr<DependencyC> dependency_c(factory->Create(x)); 
    dependency_c->DoStuff(); 
} 

Nota che la seconda versione richiesto un minor numero di dipendenze al metodo "DoIt". Ciò non significa che tali dipendenze non siano necessarie nell'intero programma (infatti, il programma utilizza ancora DependencyA e DependencyB nell'implementazione della fabbrica). Tuttavia, strutturandolo in questo modo, tale dipendenza può essere isolata solo dal codice di fabbrica, che semplifica l'altro codice, facilita la modifica delle dipendenze di DependencyC (ora solo la fabbrica, di per sé, deve essere aggiornata, non ogni luogo che crea un'istanza di DependencyC) e può anche avere alcuni vantaggi in termini di sicurezza (ad esempio se DependencyA e DependencyB sono sensibili come le password del database o le chiavi API, limitando il loro utilizzo in fabbrica riduce le possibilità di maltrattamento, rispetto ai casi in cui si passa in giro ovunque tu abbia bisogno di usare il databse o l'API, per esempio).

Nell'esempio riportato nel libro, il motivo per cui avere una fabbrica per il Order avrebbe aiutato è che avrebbe ridotto il numero di posti in cui il costruttore viene utilizzato direttamente; solo l'unico posto che ha creato la fabbrica avrebbe dovuto essere modificato per memorizzare Customer come un campo aggiuntivo della fabbrica; nessuno degli altri usi della fabbrica avrebbe bisogno di essere modificato. In confronto, senza l'uso della fabbrica, gli usi diretti del costruttore abbondano e ciascuno di essi deve essere aggiornato per ottenere in qualche modo l'accesso all'oggetto Customer.

+0

Grazie per il codice. Ma, per creare MyClassFactory2, ho bisogno di fornire p1 e p2. Se p1 e p2 sono noti solo al momento in cui ho bisogno di creare MyClass, come è diverso dall'inserire un extra nel costruttore? – leiz

+1

@leiz, se i parametri sono una dipendenza esterna, allora qualsiasi cosa fornisca quella dipendenza esterna dovrebbe anche essere in grado di fornire l'oggetto factory. Se no, allora hai ragione, non aiuta. –

3

Il vero vantaggio dell'utilizzo di una fabbrica è che si tratta di una facciata che nasconde proprio come si procede alla creazione di un oggetto che soddisfa il ruolo dell'ordine. Per essere più precisi, la Factory sa che stai facendo davvero un FooBarOrder, e nient'altro deve essere cambiato per passare dal creare sempre un FooBarOrder a volte creando un BarFooOrder. (Se Java consente di intercettare lo new e di creare una sottoclasse, non ci sarebbe bisogno di fabbriche, ma non abbastanza - ragionevolmente, per essere onesti - quindi bisogna averli. Sistemi di oggetti che consentono la sottoclasse della classe di classi sono più flessibili in questo senso.)

+0

È così che capisco anche lo schema di fabbrica. Ma la gente continua a dire che è anche utile nel caso di aggiungere dipendenza, e questo è qualcosa che non capisco. – leiz

+0

Originariamente un Ordine, creato dalla tua fabbrica, implementava IOrder. Ora vuoi avere un CustomerOrder.Supponendo che tutte le informazioni necessarie per creare un CustomerOrder siano disponibili nelle stesse informazioni necessarie per creare un Ordine o possano essere determinate da tali informazioni o staticamente, la fabbrica può ora restituire un Ordine Cliente senza alcuna modifica al codice. Se la fabbrica ha bisogno di una nuova dipendenza per aiutarla a ottenere il CustomerObject necessario per creare il CustomerOrder, allora quella modifica deve avvenire solo in fabbrica, non in ogni luogo in cui si crea un ordine. –

Problemi correlati