Questo è simile alla risposta votata, ma voglio pensare ad alta voce - forse anche altri vedono le cose in questo modo.
La OO classica utilizza costruttori per definire il contratto di "inizializzazione" pubblico per i consumatori della classe (nascondendo TUTTI i dettagli di implementazione; ovvero l'incapsulamento). Questo contratto può garantire che dopo l'istanza si disponga di un oggetto pronto per l'uso (ovvero nessuna ulteriore procedura di inizializzazione che deve essere ricordata (e dimenticata) dall'utente).
(costruttore) DI interrompe innegabilmente l'incapsulamento dei dettagli di implementazione attraverso questa interfaccia pubblica del costruttore. Finché consideriamo ancora il costruttore pubblico responsabile della definizione del contratto di inizializzazione per gli utenti, abbiamo creato un'orribile violazione dell'incapsulamento.
Esempio teorico:
La classe Foo ha 4 metodi e ha bisogno di un numero intero per l'inizializzazione, quindi il suo costruttore assomiglia a Foo (dimensione int) ed è immediatamente chiaro agli utenti della classe Foo che devono fornire una dimensione all'istanza per far funzionare Foo.
Supponiamo che questa particolare implementazione di Foo possa anche aver bisogno di un IWidget per fare il suo lavoro. L'iniezione da parte del costruttore di questa dipendenza ci farebbe creare un costruttore come Foo (dimensione int, widget IWidget)
Ciò che mi infastidisce è che ora abbiamo un costruttore che fonde i dati di inizializzazione con le dipendenze: un input è di interesse per l'utente della classe ( dimensione ), l'altro è una dipendenza interna che serve solo a confondere l'utente ed è un'implementazione dettaglio ( widget ).
Il parametro size NON è una dipendenza, è semplice un valore di inizializzazione per istanza. IoC è ideale per le dipendenze esterne (come i widget) ma non per l'inizializzazione dello stato interno.
Ancora peggio, e se il Widget fosse necessario solo per 2 dei 4 metodi su questa classe; Potrei incorrere in un'istanza ambientale per Widget anche se non può essere utilizzata!
Come compromettere / riconciliare questo?
Un approccio è passare esclusivamente alle interfacce per definire il contratto operativo; e abolire l'uso dei costruttori da parte degli utenti. Per essere coerenti, tutti gli oggetti dovrebbero essere accessibili solo attraverso le interfacce e istanziati solo attraverso una qualche forma di resolver (come un contenitore IOC / DI). Solo il contenitore può istanziare le cose.
Ciò si occupa della dipendenza Widget, ma come inizializzare la "dimensione" senza ricorrere a un metodo di inizializzazione separato sull'interfaccia Foo? Usando questa soluzione, abbiamo perso la capacità di garantire che un'istanza di Foo sia completamente inizializzata al momento dell'istanza. Peccato, perché mi piace molto l' idea e la semplicità dell'iniezione del costruttore.
Come posso ottenere l'inizializzazione garantita in questo mondo DI, quando l'inizializzazione è PIÙ di SOLO dipendenze esterne?