C'est similaire à la réponse votée mais je veux réfléchir à haute voix - peut-être que d'autres voient les choses de cette façon également.
Le OO classique utilise des constructeurs pour définir le contrat public "d'initialisation" pour les consommateurs de la classe (masquant TOUS les détails d'implémentation; aka l'encapsulation). Ce contrat peut garantir qu'après instanciation, vous disposez d'un objet prêt à l'emploi (c'est-à-dire qu'aucune étape d'initialisation supplémentaire ne doit être mémorisée (euh, oubliée) par l'utilisateur).
(constructeur) DI rompt indéniablement l'encapsulation en saignant les détails d'implémentation via cette interface de constructeur publique. Tant que nous considérons toujours le constructeur public responsable de la définition du contrat d'initialisation pour les utilisateurs, nous avons créé une horrible violation de l'encapsulation.
Exemple théorique:
La classe Foo a 4 méthodes et a besoin d'un entier pour l'initialisation, donc son constructeur ressemble à Foo (taille int) et il est immédiatement clair pour les utilisateurs de la classe Foo qu'ils doivent fournir une taille à l'instanciation pour que Foo fonctionne.
Disons que cette implémentation particulière de Foo peut également avoir besoin d'un IWidget pour faire son travail. L'injection de constructeur de cette dépendance nous ferait créer un constructeur comme Foo (int size, widget IWidget)
Ce qui me dérange à ce sujet, c'est que nous avons maintenant un constructeur qui mélange les données d'initialisation avec les dépendances - une entrée intéresse l'utilisateur de la classe ( taille ), l'autre est une dépendance interne qui ne sert qu'à confondre l'utilisateur et est une implémentation détail ( widget ).
Le paramètre size n'est PAS une dépendance - c'est simplement une valeur d'initialisation par instance. IoC est dandy pour les dépendances externes (comme le widget) mais pas pour l'initialisation de l'état interne.
Pire encore, que se passe-t-il si le widget n'est nécessaire que pour 2 des 4 méthodes de cette classe; Il se peut que je subisse une surcharge d'instanciation pour Widget même s'il ne peut pas être utilisé!
Comment compromettre / concilier cela?
Une approche consiste à passer exclusivement aux interfaces pour définir le contrat d'exploitation; et abolir l'utilisation des constructeurs par les utilisateurs. Pour être cohérent, tous les objets devraient être accessibles uniquement via des interfaces et instanciés uniquement via une forme de résolveur (comme un conteneur IOC / DI). Seul le conteneur peut instancier les choses.
Cela prend en charge la dépendance Widget, mais comment initialiser "size" sans recourir à une méthode d'initialisation distincte sur l'interface Foo? En utilisant cette solution, nous avons perdu la possibilité de nous assurer qu'une instance de Foo est complètement initialisée au moment où vous obtenez l'instance. Dommage, parce que j'aime vraiment l' idée et la simplicité de l'injection de constructeur.
Comment obtenir une initialisation garantie dans ce monde DI, lorsque l'initialisation est PLUS QUE SEULEMENT des dépendances externes?