11

Ho acquisito maggiore familiarità con il modello di fabbrica (insieme al modello di strategia) e quale grande vantaggio può avere il modello. Tuttavia, ho avuto problemi con la seguente situazione:Salvataggio dei dati con il modello di fabbrica?

In precedenza, avrei fatto qualcosa di simile a quanto segue, dove c'è una classe manager che costruisce e salva un'auto. Non c'è alcuna iniezione di dipendenze qui ed è una cattiva implementazione, specialmente quando si tenta di effettuare un test unitario.

public class CarManager 
{ 
    public static Car GetCarFromDatabase(int carId) { return new Car(); } 

    public static void SaveCar(Car car) { } 
} 

Ora vedo come avrei potuto avere diverso Factories che costruiscono automobili per me, sia che si tratti di un database, o dovunque! È fantastico! Quindi, ecco le mie domande:

Q1: E 'la mia comprensione che Factories dovrebbe solo costruire oggetti, è corretto? Se è così, e la mia seconda domanda?

Q2: Se sto seguendo il modello di fabbrica per la costruzione dei miei oggetti, come devo fare per salvare i miei oggetti? C'è un modello diverso per questo, o non capisco completamente il modello di fabbrica?

+0

le fabbriche non devono realmente costruire oggetti - il loro scopo è quello di selezionare il tipo di cemento corretta da un insieme di tipi di oggetti correlati che tutti ereditiamo dalla stessa base. Sei sicuro di voler dire Fabbriche e non Costruttori? –

risposta

14

Il modello Factory è pensato per aiutare nella creazione di oggetti. Questo è il motivo per cui è classificato come un modello di "Creazione". Per rispondere alla tua prima domanda, non dovrebbe essere usato per persistere oggetti.

Repository pattern Il modello Repository pattern è uno schema di persistenza che deve essere utilizzato per il salvataggio di oggetti in un meccanismo di persistenza o il recupero di dati da un meccanismo di persistenza. In realtà, secondo Martin Fowler, si tratta di un modello aziendale che dovrebbe essere affrontato in modo diverso rispetto al tipico modello di progettazione.

Quando si pensa alla tua domanda, si vuole guardare allo S principle in SOLID in cui si afferma che una classe dovrebbe avere una singola responsabilità, il che significa che dovrebbe avere un unico motivo per cambiare. In questo caso, quando parli di un oggetto che crea oggetti e li salva (li persiste), hai una classe che ha due motivi per cambiare. Ora, potrebbe sembrare che potrebbe essere una singola responsabilità perché un Repository può recuperare e salvare oggetti nell'applicazione e il recupero può apparire come una fabbrica (e spesso è un oggetto di fabbrica all'interno del repository), ma in ciò che stai descrivendo , il tuo oggetto ha troppe responsabilità.

+0

Grazie a @Dave White. Dopo aver visto il tuo post, ho visto un video di Pluralsight sul pattern del repository e questo era quello che stavo cercando. Grazie per la tua risposta! – JSprang

3

La fabbrica non dovrebbe salvare i dati. Un DAO (Data Access Object) o un mapper di tabella sarebbe un'idea migliore.

1

In generale, penso che vi state avvicinando da un angolo sbagliato.

È necessario identificare il problema che si sta tentando di risolvere e quindi cercare soluzioni adatte a tale problema. Mi sembra più che tu abbia scoperto un certo schema e poi stai provando ad applicarlo a ogni problema che incontri.

L'unico problema che si cita con il codice che hai postato è che non è facile testare l'unità. Una soluzione per rendere le classi più testabili è di invertire le loro dipendenze. Quindi inizierei a guardare a quali altre classi dipende questa classe, e inizierò a creare quelle dipendenze iniettabili. Come punto di partenza, ti consiglierei di leggere l'inversione delle dipendenze/l'inversione del controllo.

1

Q1 - Sì, il modello di fabbrica dovrebbe essere idealmente utilizzato per la creazione di oggetti. Quindi, puoi creare il tuo oggetto Auto usando il modello di fabbrica.

Q2 - Per salvare il tuo oggetto auto non utilizzare il modello di fabbrica.Disaccoppia la creazione dell'oggetto Car e salvando l'oggetto auto. E, è difficile suggerire un modello di design per salvare l'oggetto dell'auto senza capire i requisiti in modo accurato. Secondo me, se hai solo bisogno di salvare gli oggetti della tua auto, tutto ciò che ti serve è un metodo di salvataggio nella tua classe di manager di macchina. Non utilizzare eccessivamente i modelli di progettazione.

2

Tutto dipende dalle vostre esigenze e da come volete fare le cose, i modelli sono pratiche prive di standard, incoraggiano il riuso del codice, i modelli non sono afferrati sulla pietra. Quindi, perché non dovresti usare Modello di fabbrica per rendere la persistenza degli oggetti ?. Questo è il modo in cui ho usato tale modello per risolvere il problema di leggere/scrivere dati da/verso diversi database, forse questa non è la forma migliore di usare il pattern ma è attualmente funzionante, è estendibile, è distribuita tra i livelli e quasi tutti possono capirlo:

namespace Domain.App 
{ 
    public class PresentationClass 
    { 
     private Collection<ISomeOutput> GetData(ISomeInput1 input) 
     { 
      ServicesLogicContext logic = new ServicesLogicContext((MyType) Identifier); 
      return logic.GetSomeData(input) as Collection<ISomeOutput>; 
     } 
     private IMethodResult ExecuteSomeAction(ISomeInput2 input) 
     { 
      ServicesLogicContext logic = new ServicesLogicContext((MyType) Identifier); 
      return logic.ExecuteSomeAction(input); 
     } 
    } 
} 

namespace Domain.Logic 
{ 
    public sealed class ServicesLogicContext : ServicesLogicContextBase 
    { 
     public IList<ISomeOutput> GetSomeData(ISomeInput1 input) 
     { 
      DBServices services = DBServicesProvider.CreateServices(SomeIdentifier); 
      return DBServicesProvider.GetSomeData(input); 
     } 
     public IMethodResult ExecuteSomeAction(ISomeInput2 input) 
     { 
      DBServices services = DBServicesProvider.CreateServices(SomeIdentifier); 
      IMethodResult result = services.ExecuteSomeAction(input); 
      return result; 
     } 
    } 
} 

namespace Domain.Data 
{ 
    public abstract class DBServices : IServices 
    { 
     public virtual IList<ISomeOutput> GetSomeData(ISomeInput1 input) {...} 
     public virtual IMethodResult ExecuteSomeAction(ISomeInput2 input) {...} 
    } 

    public class DBServicesSpecific1 : DBServices 
    { 
     public override IList<ISomeOutput> GetSomeData(ISomeInput1 input) {...} 
     public override IMethodResult ExecuteSomeAction(ISomeInput2 input) {...} 
    } 

    public class DBServicesSpecific2 : DBServices 
    { 
     public override IList<ISomeOutput> GetSomeData(ISomeInput1 input) {...} 
     public override IMethodResult ExecuteSomeAction(ISomeInput2 input) {...} 
    } 

    public sealed class DBServicesProvider 
    { 
     public static DBServices CreateServices(MyType identifier) 
     { 
      DBServices result = null;  
      switch(identifier) 
      { 
       case MyType.Specific1: result = new DBServicesSpecific1(); break; 
       case MyType.Specific2: result = new DBServicesSpecific2(); break;  
      } 
      return result; 
     } 
    } 
} 
+1

+1 Grazie per un codice di esempio per me da scavare! – JSprang

+1

Hai ragione che i modelli non sono soluzioni specifiche, ma le migliori pratiche per risolvere tipi di problemi. L'implementazione specifica dovrebbe essere lasciata allo sviluppatore. Una cosa però è che il tuo codice non sembra effettivamente mostrare un esempio di fabbrica (mostra un modello di localizzazione di servizio come modello) e si interrompe dal principio S in SOLID dove la tua classe ServicesLogicContext sembra avere più responsabilità. Tuttavia, una cosa interessante quando si discute di schemi è che una sezione di codice può somigliare a modelli diversi a persone diverse ed essere comunque un codice corretto e corretto. –

Problemi correlati