Sto scrivendo un nuovo sistema e sto cercando di rimanere fedele ai principi SOLID, in particolare Interfaccia e Iniezione delle dipendenze. Stiamo attaccando da vicino allo stack Microsoft, quindi stiamo utilizzando C # e il contenitore Unity. Sono in un negozio relativamente immaturo per quanto riguarda i concetti SOLIDI, quindi cerco di mantenere le cose il più semplici possibile per tutti, incluso me stesso.
Ho uno stile in cui preferisco utilizzare la funzione di costruzione per accettare i parametri di runtime e convalidare tutti i campi di cui l'oggetto potrebbe aver bisogno in anticipo. Ciò rende difficile l'iniezione basata su un semplice costruttore e mi ha guidato lungo il percorso astratto della fabbrica.
Ho anche una dipendenza in cui ho bisogno di un elenco di interfacce. Ancora una volta questo non era qualcosa che Unity sosteneva elegantemente e ancora una volta la fabbrica astratta sembrava giusta.
Ho iniziato con idee elevate di una fabbrica astratta generica, ma ad essere onesti stavo passando un momento difficile a capire come ottenere le registrazioni dei container giuste. Se fosse stato difficile per me, sarebbe stato molto più difficile spiegarlo e venderlo alla mia squadra.
Così ho fatto un passo indietro e ho creato questo schema in cui ho un'interfaccia e un'interfaccia di fabbrica corrispondente per ciascuna delle mie dipendenze. La registrazione del contenitore diventa semplicissima.
_container.RegisterType<IChartFactory, ChartFactory>();
_container.RegisterType<IDocumentFactory, DocumentFactory>();
_container.RegisterType<IReportFactory, ReportFactory>();
_reportFactory = _container.Resolve<IReportFactory>();
_report = _reportFactory.CreateReport1(runTimeData);
Se dovessimo cambiare una dipendenza, implementeremo l'interfaccia sottostante con il minimo aggiunto di implementare anche la fabbrica corrispondente.
public class DocumentFactory : IDocumentFactory
{
public IDocument Create(string filePath)
{
return new Document(filePath);
}
}
public interface IReportFactory
{
IReport CreateReport1(object runTimeData);
IReport CreateReport2(object runTimeData);
}
public class ReportFactory : IReportFactory
{
IDocumentFactory _documentFactory;
IChartFactory _chartFactory;
public ReportFactory(IDocumentFactory documentFactory, IChartFactory chartFactory)
{
_documentFactory = documentFactory;
_chartFactory = chartFactory;
}
public IReport CreateReport1(object runTimeData)
{
return new ConcreteReport1(runTimeData, _documentFactory, _chartFactory);
}
public IReport CreateReport2(object runTimeData)
{
return new ConcreteReport2(runTimeData, _documentFactory, _chartFactory);
}
}
Lo trovo semplice da capire e da spiegare. Se la dipendenza cambia, l'implementazione di poche righe di codice per la factory sembra un piccolo prezzo da pagare rispetto alla modifica di ogni punto del sistema in cui il tipo viene aggiornato.
Altre dipendenze si stanno insinuando e tutte queste interfacce e fabbriche si sentono eccessive. Sono preoccupato per il pushback. Non sono sicuro che i meriti giustificano lo schema e non sono sicuro che lo stia facendo bene. Ogni pensiero è molto apprezzato!