Plusieurs questions ont déjà été posées avec des questions spécifiques sur injection de dépendance , telles que savoir quand l'utiliser et quels cadres existent pour cela. cependant,
Qu'est-ce qu'une injection de dépendance et quand/pourquoi devrait-elle ou ne devrait-elle pas être utilisée?
Fondamentalement, au lieu de laisser vos objets créer une dépendance ou de demander à un objet usine de les créer, vous transmettez les dépendances nécessaires à l'objet en externe, et vous en faites le problème de quelqu'un d'autre. Ce "quelqu'un" est soit un objet situé plus haut dans le graphe de dépendance, soit un injecteur de dépendance (framework) qui construit le graphe de dépendance. Une dépendance telle que je l'utilise ici est tout autre objet pour lequel l'objet actuel doit contenir une référence.
L'un des principaux avantages de l'injection de dépendance est qu'il peut faciliter les tests. Supposons que vous avez un objet qui, dans son constructeur, fait quelque chose comme:
public SomeClass() {
myObject = Factory.getObject();
}
Cela peut être gênant lorsque tout ce que vous voulez faire est de lancer des tests unitaires sur SomeClass
, en particulier si myObject
est quelque chose qui effectue un accès complexe au disque ou au réseau. Alors maintenant, vous essayez de vous moquer de myObject
, mais aussi d'intercepter l'appel de l'usine. Difficile. À la place, transmettez l'objet en tant qu'argument au constructeur. Vous avez maintenant déplacé le problème ailleurs, mais les tests peuvent devenir beaucoup plus faciles. Créez simplement une variable myObject
et transmettez-la. Le constructeur ressemblerait maintenant à ceci:
public SomeClass (MyClass myObject) {
this.myObject = myObject;
}
C'est un style d'injection de dépendance - via le constructeur. Plusieurs mécanismes sont possibles.
Lorsqu'on n'utilise pas l'injection de dépendance (comme dans les classes qui travaillent trop dans leurs constructeurs, etc.), il est de plus en plus difficile d'isoler les composants lors des tests unitaires.
En 2013, lorsque j'ai écrit cette réponse, il s'agissait d'un thème majeur du Google Testing Blog . Cela reste le plus gros avantage pour moi, car vous n’avez peut-être pas toujours besoin de plus de flexibilité dans votre conception au moment de l’exécution (par exemple, pour le localisateur de services ou des modèles similaires), mais vous devez souvent pouvoir isoler vos classes pendant les tests.
La meilleure définition que j'ai trouvée jusqu'à présent est une de James Shore :
"Injection de dépendance" est une valeur de 25 dollars terme pour un concept de 5 cents. [...] L'injection de dépendance signifie donner un object ses variables d'instance. [...].
Il y a un article de Martin Fowler qui pourrait également s'avérer utile.
L'injection de dépendance fournit essentiellement les objets dont un objet a besoin (ses dépendances) au lieu de le faire construire par lui-même. C'est une technique très utile pour les tests, car elle permet de simuler ou d'éliminer des dépendances.
Les dépendances peuvent être injectées dans des objets par de nombreux moyens (tels que l'injection de constructeur ou l'injection de setter). On peut même utiliser des infrastructures d'injection de dépendances spécialisées (Spring, par exemple), mais elles ne sont certainement pas nécessaires. Vous n'avez pas besoin que ces frameworks aient une injection de dépendance. Instancier et passer explicitement des objets (dépendances) est aussi bien une injection qu'une injection par framework.
J'ai trouvé cet exemple amusant en termes de couplage lâche :
Toute application est composée de nombreux objets qui collaborent les uns avec les autres pour effectuer des tâches utiles. Traditionnellement, chaque objet est responsable de l'obtention de ses propres références aux objets dépendants (dépendances) avec lesquels il collabore. Cela conduit à des classes fortement couplées et à un code difficile à tester.
Par exemple, considérons un objet Car
.
A Car
dépend des roues, du moteur, du carburant, de la batterie, etc. pour fonctionner. Traditionnellement, nous définissons la marque de ces objets dépendants en même temps que la définition de l'objet Car
.
sans injection de dépendance (DI):
class Car{
private Wheel wh = new NepaliRubberWheel();
private Battery bt = new ExcideBattery();
//The rest
}
Ici, l'objet Car
est responsable de la création des objets dépendants.
Que faire si nous voulons changer le type de son objet dépendant - disons Wheel
- après les premières ponctions NepaliRubberWheel()
? Nous devons recréer l'objet Car avec sa nouvelle dépendance, par exemple ChineseRubberWheel()
, mais seul le fabricant Car
peut le faire.
Alors qu'est-ce que le Dependency Injection
fait pour nous ...?
Lors de l'utilisation de l'injection de dépendance, les objets reçoivent leurs dépendances au moment de l'exécution plutôt qu'au moment de la compilation (heure de fabrication de la voiture) . Pour que nous puissions maintenant changer la Wheel
à tout moment. Ici, le dependency
(wheel
) peut être injecté dans Car
au moment de l'exécution.
Après avoir utilisé l'injection de dépendance:
Ici, nous injectons les dépendances (roue et batterie) à l'exécution . D'où le terme: Injection de dépendance.
class Car{
private Wheel wh = // Inject an Instance of Wheel (dependency of car) at runtime
private Battery bt = // Inject an Instance of Battery (dependency of car) at runtime
Car(Wheel wh,Battery bt) {
this.wh = wh;
this.bt = bt;
}
//Or we can have setters
void setWheel(Wheel wh) {
this.wh = wh;
}
}
L'injection de dépendance est une pratique dans laquelle les objets sont conçus de manière à recevoir leurs instances d'autres morceaux de code, au lieu de les construire en interne. Cela signifie que tout objet implémentant l'interface requise par l'objet peut être remplacé sans changer le code, ce qui simplifie les tests et améliore le découplage.
Par exemple, considérons ces classes:
public class PersonService {
public void addManager( Person employee, Person newManager ) { ... }
public void removeManager( Person employee, Person oldManager ) { ... }
public Group getGroupByManager( Person manager ) { ... }
}
public class GroupMembershipService() {
public void addPersonToGroup( Person person, Group group ) { ... }
public void removePersonFromGroup( Person person, Group group ) { ... }
}
Dans cet exemple, l'implémentation de PersonService::addManager
et PersonService::removeManager
nécessiterait une instance de GroupMembershipService
pour effectuer son travail. Sans injection de dépendance, la méthode traditionnelle consiste à instancier une nouvelle variable GroupMembershipService
dans le constructeur de PersonService
et à utiliser cet attribut d'instance dans les deux fonctions. Cependant, si le constructeur de GroupMembershipService
a plusieurs choses à faire, ou pire, il existe des "réglages" d'initialisation qui doivent être appelés sur la GroupMembershipService
, le code croît assez rapidement et la PersonService
dépend non seulement de la GroupMembershipService
tout ce dont dépend GroupMembershipService
. En outre, le lien avec GroupMembershipService
est codé en dur dans PersonService
, ce qui signifie que vous ne pouvez pas "simuler" une GroupMembershipService
à des fins de test ou pour utiliser un modèle de stratégie dans différentes parties de votre application.
Avec Dependency Injection, au lieu d’instancier la GroupMembershipService
dans votre PersonService
, transmettez-le au constructeur PersonService
ou ajoutez une propriété (getter and setter) pour en définir une instance locale. Cela signifie que votre PersonService
n'a plus à s'inquiéter de la façon de créer une GroupMembershipService
, elle accepte uniquement celles qui lui sont données et fonctionne avec elles. Cela signifie également que tout ce qui est une sous-classe de GroupMembershipService
ou qui implémente l'interface GroupMembershipService
peut être "injecté" dans la PersonService
, et la PersonService
n'a pas besoin de connaître le changement.
La réponse acceptée est bonne - mais je voudrais ajouter à cela que DI est très semblable au traitement classique consistant à éviter les constantes codées en dur dans le code.
Lorsque vous utilisez une constante comme un nom de base de données, vous la déplacez rapidement de l'intérieur du code vers un fichier de configuration, puis transmettez une variable contenant cette valeur à l'emplacement où elle est requise. La raison en est que ces constantes changent généralement plus souvent que le reste du code. Par exemple, si vous souhaitez tester le code dans une base de données de test.
DI est analogue à cela dans le monde de la programmation orientée objet. Les valeurs présentes au lieu de littéraux constants sont des objets entiers - mais la raison pour déplacer le code les créant en dehors du code de classe est similaire: les objets changent plus souvent que le code qui les utilise. Les tests constituent un cas important dans lequel un tel changement est nécessaire.
Essayons un exemple simple avec Car et Engine classes, toute voiture a besoin d’un moteur pour aller n’importe où, du moins pour le moment. Donc, ci-dessous, à quoi ressemblera le code sans injection de dépendance.
public class Car
{
public Car()
{
GasEngine engine = new GasEngine();
engine.Start();
}
}
public class GasEngine
{
public void Start()
{
Console.WriteLine("I use gas as my fuel!");
}
}
Et pour instancier la classe Car, nous utiliserons le code suivant:
Car car = new Car();
Le problème avec ce code que nous avons étroitement couplé à GasEngine et si nous décidons de le changer à ElectricityEngine, nous devrons alors réécrire la classe Car. Et plus l'application est volumineuse, plus nous aurons de problèmes et de maux de tête à ajouter et à utiliser un nouveau type de moteur.
En d'autres termes, avec cette approche, notre classe de voiture de haut niveau dépend de la classe GasEngine de niveau inférieur, qui enfreint le principe d'inversion de dépendance (DIP) de SOLID. DIP suggère de dépendre d'abstractions et non de classes concrètes. Donc pour satisfaire cela, nous introduisons l'interface IEngine et réécrivons le code comme ci-dessous:
public interface IEngine
{
void Start();
}
public class GasEngine : IEngine
{
public void Start()
{
Console.WriteLine("I use gas as my fuel!");
}
}
public class ElectricityEngine : IEngine
{
public void Start()
{
Console.WriteLine("I am electrocar");
}
}
public class Car
{
private readonly IEngine _engine;
public Car(IEngine engine)
{
_engine = engine;
}
public void Run()
{
_engine.Start();
}
}
Maintenant, notre classe Car dépend uniquement de l'interface IEngine, et non d'une implémentation spécifique du moteur. Maintenant, le seul truc est de savoir comment créer une instance de la voiture et lui donner une classe de moteur concrète telle que GasEngine ou ElectricityEngine. C'est là que Injection de dépendance entre en jeu.
Car gasCar = new Car(new GasEngine());
gasCar.Run();
Car electroCar = new Car(new ElectricityEngine());
electroCar.Run();
Ici, nous injectons (passons) notre dépendance (instance de moteur) au constructeur de voitures. Alors maintenant, nos classes ont un couplage lâche entre les objets et leurs dépendances, et nous pouvons facilement ajouter de nouveaux types de moteurs sans changer la classe Car.
Le principal avantage de Dependency Injection est que les classes sont plus faiblement couplées, car elles n’ont pas de dépendances codées en dur. Ceci est conforme au principe d'inversion de dépendance mentionné ci-dessus. Au lieu de référencer des implémentations spécifiques, les classes demandent des abstractions (généralement interfaces ) qui leur sont fournies lors de la construction de la classe.
Donc à la fin L’injection de dépendance n’est qu’une technique pour réaliser un couplage lâche entre les objets et leurs dépendances . Plutôt que d'instancier directement les dépendances dont cette classe a besoin dans Pour pouvoir exécuter ses actions, des dépendances sont fournies à la classe (le plus souvent) par injection de constructeur.
De plus, lorsque nous avons de nombreuses dépendances, il est très recommandé d’utiliser des conteneurs Inversion of Control (IoC) pour indiquer quelles interfaces doivent être mappées vers quelles implémentations concrètes pour toutes nos dépendances et pour que nous puissions les résoudre lors de la construction. notre objet. Par exemple, nous pourrions spécifier dans le mappage du conteneur IoC que la dépendance IEngine devrait être mappée à la classe GasEngine et que nous demandons au conteneur IoC une instance de notre Car class , il construira automatiquement notre classe Car avec un GasEngine dépendance passé.
UPDATE: Regardé récemment un cours sur EF Core de Julie Lerman et également apprécié sa courte définition de DI.
L'injection de dépendance est un modèle permettant à votre application d'injecter objets à la volée aux classes qui en ont besoin, sans forcer ceux les classes à être responsables de ces objets. Cela permet à votre code d’être plus faiblement couplé, et Entity Framework Core s'y connecte système de services.
Imaginons que vous vouliez aller pêcher:
Sans injection de dépendance, vous devez vous occuper de tout vous-même. Vous devez trouver un bateau, acheter une canne à pêche, chercher un appât, etc. C'est possible, bien sûr, mais cela vous impose beaucoup de responsabilités. En termes logiciels, cela signifie que vous devez effectuer une recherche pour toutes ces choses.
Avec l'injection de dépendance, une autre personne se charge de toute la préparation et met à votre disposition le matériel requis. Vous recevrez ("soyez injecté") le bateau, la canne à pêche et l’appât - prêts à l’emploi.
Ceci est l'explication la plus simple concernant Dependency Injection et Dependency Injection Container que j'ai jamais vu:
Dependency Injection et dependency Injection Containers sont deux choses différentes:
Vous n'avez pas besoin d'un conteneur pour faire l'injection de dépendance. Cependant, un conteneur peut vous aider.
L'injection de dépendance ne signifie-t-elle pas simplement l'utilisation de constructeurs paramétrés et de paramètres publics?
L'article de James Shore montre les exemples suivants pour comparaison .
Constructeur sans injection de dépendance:
public class Example {
private DatabaseThingie myDatabase;
public Example() {
myDatabase = new DatabaseThingie();
}
public void doStuff() {
...
myDatabase.getData();
...
}
}
Constructeur avec injection de dépendance:
public class Example {
private DatabaseThingie myDatabase;
public Example(DatabaseThingie useThisDatabaseInstead) {
myDatabase = useThisDatabaseInstead;
}
public void doStuff() {
...
myDatabase.getData();
...
}
}
Pour rendre le concept d’injection de dépendance simple à comprendre. Prenons un exemple de bouton d’interrupteur pour allumer/éteindre une ampoule.
Switch a besoin de savoir à l'avance à quelle ampoule je suis connecté (dépendance codée en dur). Alors,
Interrupteur -> L’interrupteur PermanentBulb // est directement branché sur l’ampoule fixe, les tests ne sont pas possibles facilement
Switch(){
PermanentBulb = new Bulb();
PermanentBulb.Toggle();
}
Interrupteur sait seulement que je dois allumer/éteindre l’ampoule qui m’est transmise. Alors,
Commutateur -> Ampoule 1 OR Ampoule 2 OR NightBulb (dépendance injectée)
Switch(AnyBulb){ //pass it whichever bulb you like
AnyBulb.Toggle();
}
Modification James Exemple pour interrupteur et ampoule:
public class SwitchTest {
TestToggleBulb() {
MockBulb mockbulb = new MockBulb();
// MockBulb is a subclass of Bulb, so we can
// "inject" it here:
Switch switch = new Switch(mockBulb);
switch.ToggleBulb();
mockBulb.AssertToggleWasCalled();
}
}
public class Switch {
private Bulb myBulb;
public Switch() {
myBulb = new Bulb();
}
public Switch(Bulb useThisBulbInstead) {
myBulb = useThisBulbInstead;
}
public void ToggleBulb() {
...
myBulb.Toggle();
...
}
}`
L’intérêt de Dependency Injection (DI) est de garder le code source de l’application clean et stable :
Pratiquement, chaque modèle de conception sépare les préoccupations pour que les modifications futures affectent le nombre minimal de fichiers.
Le domaine spécifique de DI est la délégation de configuration de dépendance et d'initialisation.
Si vous travaillez occasionnellement en dehors de Java, rappelez-vous que source
est souvent utilisé dans de nombreux langages de script (Shell, Tcl, etc., ou même import
en Python mal utilisé à cette fin).
Considérez le script dependent.sh
simple:
#!/bin/sh
# Dependent
touch "one.txt" "two.txt"
archive_files "one.txt" "two.txt"
Le script est dépendant: il ne s'exécutera pas seul (archive_files
n'est pas défini).
Vous définissez archive_files
dans le script d'implémentation archive_files_Zip.sh
(en utilisant Zip
dans ce cas):
#!/bin/sh
# Dependency
function archive_files {
Zip files.Zip "$@"
}
Au lieu de source
- script d'implémentation directement dans celui qui est dépendant, vous utilisez un "conteneur" injector.sh
qui enveloppe les deux "composants":
#!/bin/sh
# Injector
source ./archive_files_Zip.sh
source ./dependent.sh
Le archive_files
dépendance vient juste d'être injecté dans dépendant script.
Vous pourriez avoir une dépendance injectée qui implémente archive_files
en utilisant tar
ou xz
.
Si le script dependent.sh
utilisait directement les dépendances, l'approche s'appellerait recherche de dépendance (ce qui est opposé à injection de dépendance):
#!/bin/sh
# Dependent
# dependency look-up
source ./archive_files_Zip.sh
touch "one.txt" "two.txt"
archive_files "one.txt" "two.txt"
Maintenant, le problème est que le "composant" dépendant doit effectuer l'initialisation lui-même.
Le code source du "composant" n'est ni clean ni stable car chaque changement d'initialisation des dépendances nécessite également une nouvelle version du fichier de code source de "components".
DI n’est pas aussi largement mis en avant et popularisé que dans les frameworks Java.
Mais c’est une approche générique pour diviser les préoccupations de:
L'utilisation de la configuration uniquement avec dépendance n'aide pas, car le nombre de paramètres de configuration peut changer par dépendance (par exemple, un nouveau type d'authentification), ainsi que le nombre de types de dépendances pris en charge (par exemple, le nouveau type de base de données).
Toutes les réponses ci-dessus sont bonnes, mon objectif est d'expliquer le concept de manière simple, de manière à ce que toute personne sans connaissance en programmation puisse également comprendre le concept
L'injection de dépendance est l'un des modèles de conception qui nous aide à créer des systèmes complexes de manière plus simple.
Nous pouvons voir une grande variété d'applications de ce modèle dans notre vie quotidienne . Certains exemples sont magnétophone, VCD, lecteur de CD, etc.
L'image ci-dessus est une image d'un magnétophone portable, bobine à bobine, du milieu du XXe siècle. La source .
L’intention principale d’un magnétophone est d’enregistrer ou de reproduire un son.
Lors de la conception d'un système, il faut une bobine pour enregistrer ou lire du son ou de la musique. Il y a deux possibilités pour concevoir ce système
Si nous utilisons le premier, nous devons ouvrir la machine pour changer de bobine ... si nous optons pour le second, qui consiste à placer un crochet pour bobine, nous obtenons un avantage supplémentaire en jouant de la musique en changeant de bobine. . et aussi en réduisant la fonction uniquement au jeu de la bobine.
De même, l'injection de dépendance consiste à externaliser les dépendances pour se concentrer uniquement sur la fonctionnalité spécifique du composant, de manière à ce que des composants indépendants puissent être couplés ensemble pour former un système complexe.
Les principaux avantages que nous avons obtenus en utilisant l’injection de dépendance.
De nos jours, ce concept constitue la base des frameworks bien connus dans le monde de la programmation . Les Spring Angular, etc. sont les frameworks logiciels bien connus construits sur le dessus de ce concept.
L'injection de dépendance est un modèle utilisé pour créer des occurrences d'objets sur lesquelles s'appuient d'autres objets sans savoir au moment de la compilation quelle classe sera utilisée pour fournir cette fonctionnalité ou simplement le mode d'injection de propriétés à un objet est appelé injection de dépendance.
Exemple d'injection de dépendance
Auparavant, nous écrivons du code comme celui-ci
Public MyClass{
DependentClass dependentObject
/*
At somewhere in our code we need to instantiate
the object with new operator inorder to use it or perform some method.
*/
dependentObject= new DependentClass();
dependentObject.someMethod();
}
Avec l'injection de dépendance, l'injecteur de dépendance enlève l'instanciation pour nous
Public MyClass{
/* Dependency injector will instantiate object*/
DependentClass dependentObject
/*
At somewhere in our code we perform some method.
The process of instantiation will be handled by the dependency injector
*/
dependentObject.someMethod();
}
Vous pouvez aussi lire
Différence entre l'inversion du contrôle et l'injection de dépendance
L'injection de dépendance (DI) signifie découpler les objets qui dépendent les uns des autres. Dire que l’objet A dépend de l’objet B, l’idée est donc de découpler ces objets les uns des autres. Nous n’avons pas besoin de coder l’objet en utilisant un nouveau mot-clé, mais plutôt de partager les dépendances avec les objets lors de l’exécution malgré le temps de compilation .
Nous n’avons pas besoin de coder l’objet avec un nouveau mot clé, mais plutôt de définir la dépendance du bean dans le fichier de configuration. Le conteneur à ressort sera responsable de la connexion de tous.
La COI est un concept général qui peut s’exprimer de différentes manières. L’injection de dépendance est un exemple concret de la COI.
Une DI basée sur un constructeur est réalisée lorsque le conteneur appelle un constructeur de classe avec un certain nombre d'arguments, chacun représentant une dépendance sur une autre classe.
public class Triangle {
private String type;
public String getType(){
return type;
}
public Triangle(String type){ //constructor injection
this.type=type;
}
}
<bean id=triangle" class ="com.test.dependencyInjection.Triangle">
<constructor-arg value="20"/>
</bean>
La DI basée sur le Setter est accomplie par les méthodes de définition d'appel du conteneur sur vos beans après avoir appelé un constructeur sans argument ou une méthode de fabrique statique sans argument pour instancier votre bean.
public class Triangle{
private String type;
public String getType(){
return type;
}
public void setType(String type){ //setter injection
this.type = type;
}
}
<!-- setter injection -->
<bean id="triangle" class="com.test.dependencyInjection.Triangle">
<property name="type" value="equivialteral"/>
REMARQUE: Il est conseillé d'utiliser des arguments de constructeur pour les dépendances obligatoires et des paramètres pour les dépendances facultatives. Notez que si nous utilisons une annotation basée sur l'annotation @Required sur un setter, elle peut être utilisée pour créer des setters en tant que dépendances requises.
La meilleure analogie que je puisse imaginer est celle du chirurgien et de son ou ses assistants dans un bloc opératoire où le chirurgien est la personne principale et son assistant qui fournit les divers composants chirurgicaux quand il en a besoin, afin que le chirurgien puisse se concentrer chose qu’il fait le mieux (chirurgie). Sans l'assistant, le chirurgien doit se procurer lui-même les composants chaque fois qu'il en a besoin.
Pour résumer, DI est une technique permettant de supprimer une responsabilité supplémentaire commune (fardeau) sur les composants pour aller chercher les composants dépendants, en les leur fournissant.
DI vous rapproche du principe de la responsabilité unique (RS), comme le surgeon who can concentrate on surgery
.
Quand utiliser DI: Je recommanderais d'utiliser DI dans presque tous les projets de production (petits/grands), en particulier dans des environnements professionnels en constante évolution :)
Pourquoi: Parce que vous voulez que votre code soit facilement testable, simulable, etc. afin que vous puissiez rapidement tester vos modifications et le diffuser sur le marché. En outre, pourquoi n’en auriez-vous pas besoin lorsque vous disposez de nombreux outils/cadres gratuits impressionnants pour vous aider dans votre cheminement vers une base de code où vous avez plus de contrôle.
Cela signifie que les objets ne doivent avoir que le nombre de dépendances requis pour effectuer leur travail et que ces dépendances doivent être peu nombreuses. De plus, les dépendances d’un objet devraient être sur des interfaces et non sur des objets «concrets», lorsque cela est possible. (Un objet concret est un objet créé avec le mot-clé new.) Un couplage lâche favorise une plus grande réutilisabilité, une facilité de maintenance et vous permet de fournir facilement des objets fictifs au lieu de services coûteux.
L’injection de dépendance (ID), également connue sous le nom d’inversion de contrôle (IoC), peut être utilisée comme technique pour encourager ce couplage lâche.
Il existe deux approches principales pour la mise en œuvre de l'ID:
C’est la technique de passer des dépendances d’objets à son constructeur.
Notez que le constructeur accepte une interface et non un objet concret. Notez également qu'une exception est levée si le paramètre orderDao est null. Cela souligne l'importance de recevoir une dépendance valide. À mon avis, l'injection de constructeur est le mécanisme privilégié pour donner à un objet ses dépendances. Lors de l'appel de l'objet, le développeur sait clairement quelles dépendances doivent être attribuées à l'objet «Person» pour une exécution correcte.
Mais prenons l'exemple suivant… Supposons que vous ayez une classe avec dix méthodes sans dépendance, mais que vous ajoutiez une nouvelle méthode qui dépende d'IDAO. Vous pouvez changer le constructeur pour utiliser l'injection de constructeur, mais cela peut vous obliger à modifier tous les appels de constructeur. Alternativement, vous pouvez simplement ajouter un nouveau constructeur prenant la dépendance, mais comment un développeur peut-il savoir facilement quand utiliser un constructeur par rapport à un autre. Enfin, si la dépendance est très coûteuse à créer, pourquoi devrait-elle être créée et transmise au constructeur alors qu'elle ne peut être utilisée que rarement? La «Setter Injection» est une autre technique d’ID pouvant être utilisée dans de telles situations.
Setter Injection n'oblige pas les dépendances à être transmises au constructeur. Au lieu de cela, les dépendances sont définies sur les propriétés publiques exposées par l'objet dans le besoin. Comme nous l’avons dit précédemment, les principaux facteurs de motivation sont:
Voici l'exemple de ce à quoi le code ci-dessus ressemblerait:
public class Person {
public Person() {}
public IDAO Address {
set { addressdao = value; }
get {
if (addressdao == null)
throw new MemberAccessException("addressdao" +
" has not been initialized");
return addressdao;
}
}
public Address GetAddress() {
// ... code that uses the addressdao object
// to fetch address details from the datasource ...
}
// Should not be called directly;
// use the public property instead
private IDAO addressdao;
Exemple, nous avons 2 classes Client
et Service
. Client
utilisera Service
public class Service {
public void doSomeThingInService() {
// ...
}
}
Voie 1)
public class Client {
public void doSomeThingInClient() {
Service service = new Service();
service.doSomeThingInService();
}
}
Voie 2)
public class Client {
Service service = new Service();
public void doSomeThingInClient() {
service.doSomeThingInService();
}
}
Voie 3)
public class Client {
Service service;
public Client() {
service = new Service();
}
public void doSomeThingInClient() {
service.doSomeThingInService();
}
}
1) 2) 3) Utilisation de
Client client = new Client();
client.doSomeThingInService();
Avantages
Désavantages
Client
classService
, nous devons modifier le code dans tous les espaces create Service
objectVoie 1) Injection constructeur
public class Client {
Service service;
Client(Service service) {
this.service = service;
}
// Example Client has 2 dependency
// Client(Service service, IDatabas database) {
// this.service = service;
// this.database = database;
// }
public void doSomeThingInClient() {
service.doSomeThingInService();
}
}
En utilisant
Client client = new Client(new Service());
// Client client = new Client(new Service(), new SqliteDatabase());
client.doSomeThingInClient();
Voie 2) Injection de poseur
public class Client {
Service service;
public void setService(Service service) {
this.service = service;
}
public void doSomeThingInClient() {
service.doSomeThingInService();
}
}
En utilisant
Client client = new Client();
client.setService(new Service());
client.doSomeThingInClient();
Voie 3) Injection d'interface
Vérifiez https://en.wikipedia.org/wiki/Dependency_injection
===
Maintenant, ce code est déjà suivi de Dependency Injection
et il est plus facile de tester la classe Client
.
Cependant, nous utilisons toujours new Service()
plusieurs fois et il n’est pas bon de changer de constructeur Service
. Pour éviter cela, nous pouvons utiliser un injecteur DI comme
1) Manuel simple Injector
public class Injector {
public static Service provideService(){
return new Service();
}
public static IDatabase provideDatatBase(){
return new SqliteDatabase();
}
public static ObjectA provideObjectA(){
return new ObjectA(provideService(...));
}
}
En utilisant
Service service = Injector.provideService();
2) Utiliser la bibliothèque: Pour Android dagger2
Avantages
Service
, il vous suffit de le changer dans la classe InjectorConstructor Injection
, lorsque vous regardez le constructeur de Client
, vous voyez combien de dépendances de Client
classeDésavantages
Constructor Injection
, l'objet Service
est créé lorsque Client
est créé. Parfois, la fonction est utilisée dans Client
. La classe sans utilisation Service
ainsi créée Service
est perduehttps://en.wikipedia.org/wiki/Dependency_injection
Une dépendance est un objet qui peut être utilisé (
Service
)
Une injection est le passage d'une dépendance (Service
) à un objet dépendant (Client
) qui l'utiliserait
Je pense que puisque tout le monde a écrit pour DI, laissez-moi poser quelques questions.
Ceci est basé sur la réponse @Adam N publiée.
Pourquoi PersonService n'a-t-il plus à s'inquiéter de GroupMembershipService? Vous venez de mentionner que GroupMembership a plusieurs éléments (objets/propriétés) dont il dépend. Si GMService était requis dans PService, vous l'auriez comme propriété. Vous pouvez vous en moquer, que vous l'ayez injecté ou non. La seule fois où j'aimerais l'injecter, c'est si GMService a des classes enfants plus spécifiques, que vous ne saurez pas jusqu'à l'exécution. Ensuite, vous voudriez injecter la sous-classe. Ou si vous vouliez utiliser cela comme singleton ou prototype. Pour être honnête, le fichier de configuration contient tout ce qui est codé en dur en ce qui concerne la sous-classe d’un type (interface) qu’il va injecter pendant la compilation.
MODIFIER
Un beau commentaire de Jose Maria Arranz sur DI
DI accroît la cohésion en éliminant le besoin de déterminer le sens de la dépendance et d'écrire le code de la colle.
Faux. La direction des dépendances est sous forme XML ou sous forme d'annotations, vos dépendances sont écrites sous forme de code XML et d'annotations. XML et les annotations SONT du code source.
DI réduit le couplage en rendant tous vos composants modulaires (c'est-à-dire interchangeables) et en disposant d'interfaces bien définies les uns des autres.
Faux. Vous n'avez pas besoin d'un framework DI pour construire un code modulaire basé sur des interfaces.
À propos de remplaçable: avec une très simple archive .properties et Class.forName, vous pouvez définir quelles classes peuvent changer. Si N'IMPORTE QUELLE classe de votre code peut être changée, utilisez un langage de script. En passant, les annotations ne peuvent pas être changées sans recompilation.
À mon avis, il existe une seule raison pour les cadres DI: la réduction du plateau de la chaudière. Avec un système d'usine bien fait, vous pouvez faire la même chose, plus contrôlée et plus prévisible que votre infrastructure DI préférée. Les infrastructures DI promettent une réduction du code (XML et les annotations sont également du code source). Le problème est que la réduction de la plaque de la chaudière n’est réelle que dans des cas très simples (une instance par classe et similaire), parfois, dans le monde réel, choisir l’objet de service approprié n’est pas aussi simple que de mapper une classe sur un objet singleton.
Injection de dépendance signifie un moyen (en fait any-way) d’une partie du code (par exemple une classe) d’avoir accès aux dépendances (autres parties du code, par exemple les autres classes, selon manière modulaire sans codage en dur (pour pouvoir changer ou être annulé librement, ou même être chargé à un autre moment, au besoin)
(et ps, oui, c'est devenu un nom trop surfacé à 25 $ pour un concept plutôt simple)}, mon .25
cents
Je sais qu'il existe déjà de nombreuses réponses, mais j'ai trouvé cela très utile: http://tutorials.jenkov.com/dependency-injection/index.html
Aucune dépendance:
public class MyDao {
protected DataSource dataSource =
new DataSourceImpl("driver", "url", "user", "password");
//data access methods...
public Person readPerson(int primaryKey) {...}
}
Dépendance:
public class MyDao {
protected DataSource dataSource = null;
public MyDao(String driver, String url, String user, String
password){
this.dataSource = new DataSourceImpl(driver, url, user, password);
}
//data access methods...
public Person readPerson(int primaryKey)
{...}
}
Notez que l'instanciation DataSourceImpl
est déplacée dans un constructeur. Le constructeur prend quatre paramètres qui sont les quatre valeurs requises par la variable DataSourceImpl
. Bien que la classe MyDao
dépend toujours de ces quatre valeurs, elle ne satisfait plus ces dépendances elle-même. Ils sont fournis par n'importe quelle classe créant une instance MyDao
.
Les réponses les plus courantes ne sont d'aucune aide, car elles définissent l'injection de dépendance d'une manière inutile. Admettons que par "dépendance", nous entendons un autre objet préexistant dont notre objet X a besoin. Mais nous ne disons pas que nous faisons "injection de dépendance" quand nous disons
$foo = Foo->new($bar);
Nous appelons simplement cela passer des paramètres dans le constructeur. Nous le faisons régulièrement depuis que les constructeurs ont été inventés.
"L'injection de dépendance" est considérée comme un type "d'inversion de contrôle", ce qui signifie qu'une certaine logique est retirée de l'appelant. Ce n'est pas le cas lorsque l'appelant transmet des paramètres. Par conséquent, si cela était DI, DI n'impliquerait pas l'inversion de contrôle.
DI signifie qu'il existe un niveau intermédiaire entre l'appelant et le constructeur qui gère les dépendances. Un Makefile est un exemple simple d'injection de dépendance. "L'appelant" est la personne qui tape "make bar" sur la ligne de commande et le "constructeur" est le compilateur. Le Makefile spécifie que la barre dépend de foo, et fait un
gcc -c foo.cpp; gcc -c bar.cpp
avant de faire un
gcc foo.o bar.o -o bar
La personne qui tape "make bar" n'a pas besoin de savoir que bar dépend de foo. La dépendance a été injectée entre "make bar" et gcc.
L'objectif principal du niveau intermédiaire n'est pas simplement de transmettre les dépendances au constructeur, mais de répertorier toutes les dépendances dans un seul emplacement , et de les masquer au codeur (et non de les fournir au codeur) .
Habituellement, le niveau intermédiaire fournit des fabriques pour les objets construits, qui doivent fournir un rôle que chaque type d'objet demandé doit remplir. En effet, en ayant un niveau intermédiaire qui cache les détails de la construction, vous avez déjà subi la pénalité d'abstraction imposée par les usines. Vous pouvez donc tout aussi bien utiliser des usines.
L’injection de dépendance est une solution possible à ce que l’on pourrait généralement appeler l’exigence «d’obscurcissement de la dépendance». L'obscurcissement par dépendance est une méthode permettant de supprimer le caractère "évident" du processus consistant à créer une dépendance vis-à-vis d'une classe qui l'exige et donc de masquer, d'une certaine manière, la fourniture de ladite dépendance à ladite classe. Ce n'est pas forcément une mauvaise chose. En fait, en masquant la manière dont une dépendance est fournie à une classe, un élément extérieur à la classe est responsable de la création de la dépendance, ce qui signifie que, dans différents scénarios, une implémentation différente de la dépendance peut être fournie à la classe sans apporter de modification. à la classe. Ceci est idéal pour basculer entre les modes de production et de test (par exemple, en utilisant une dépendance de service «fictive»).
Malheureusement, le mauvais côté est que certaines personnes ont supposé que vous aviez besoin d'un framework spécialisé pour faire de l'obscurcissement des dépendances et que vous êtes en quelque sorte un programmeur "mineur" si vous choisissez de ne pas utiliser un framework particulier pour le faire. Un autre mythe extrêmement troublant, selon de nombreuses personnes, est que l’injection de dépendance est le seul moyen d’obtenir l’obscurcissement de la dépendance. Ceci est manifestement, historiquement et évidemment à 100% faux, mais vous aurez du mal à convaincre certaines personnes qu’il existe des alternatives à l’injection de dépendance pour vos besoins d’obscurcissement de la dépendance.
Les programmeurs ont compris depuis des années l'exigence de dépendance liée à la dépendance et de nombreuses solutions alternatives ont été développées avant et après la conception de l'injection de dépendance. Il existe des modèles d’usine, mais de nombreuses options utilisant ThreadLocal ne nécessitent pas d’injection dans une instance particulière - la dépendance est effectivement injectée dans le thread, ce qui présente l’avantage de rendre l’objet disponible (via des méthodes pratiques de getter statique) à any. class qui le nécessite sans avoir à ajouter des annotations aux classes qui en ont besoin et à configurer un "collage" XML complexe pour que cela se produise. Lorsque vos dépendances sont nécessaires à la persistance (JPA/JDO ou autre), cela vous permet de réaliser la "persistance transanale" beaucoup plus facilement et avec un modèle de domaine et des classes de modèle métier constitués uniquement de POJO (c'est-à-dire sans annotations spécifiques/verrouillées).
From the Book, ' Développeur Java bien ancré: Techniques essentielles de Java 7 et de la programmation polyglotte
DI est une forme particulière d’IoC, dans laquelle le processus de recherche de vos dépendances est en dehors du contrôle direct de votre code en cours d'exécution.
L'injection de dépendance (DI) est l'une des formes de conception, qui utilise la fonctionnalité de base de OOP - la relation entre un objet et un autre. Alors que l'héritage hérite d'un objet pour créer un autre objet plus complexe et spécifique, une relation ou une association crée simplement un pointeur sur un autre objet à partir d'un objet à l'aide d'un attribut. La puissance de DI est combinée à d’autres fonctionnalités de OOP, tout comme les interfaces et le code caché . Supposons que nous ayons un client (abonné) dans la bibliothèque, qui ne peut emprunter qu’un livre pour plus de simplicité.
Interface du livre:
package com.deepam.hidden;
public interface BookInterface {
public BookInterface setHeight(int height);
public BookInterface setPages(int pages);
public int getHeight();
public int getPages();
public String toString();
}
Ensuite, nous pouvons avoir plusieurs types de livres. un de type est fiction:
package com.deepam.hidden;
public class FictionBook implements BookInterface {
int height = 0; // height in cm
int pages = 0; // number of pages
/** constructor */
public FictionBook() {
// TODO Auto-generated constructor stub
}
@Override
public FictionBook setHeight(int height) {
this.height = height;
return this;
}
@Override
public FictionBook setPages(int pages) {
this.pages = pages;
return this;
}
@Override
public int getHeight() {
// TODO Auto-generated method stub
return height;
}
@Override
public int getPages() {
// TODO Auto-generated method stub
return pages;
}
@Override
public String toString(){
return ("height: " + height + ", " + "pages: " + pages);
}
}
Les abonnés peuvent maintenant être associés au livre:
package com.deepam.hidden;
import Java.lang.reflect.Constructor;
import Java.lang.reflect.InvocationTargetException;
public class Subscriber {
BookInterface book;
/** constructor*/
public Subscriber() {
// TODO Auto-generated constructor stub
}
// injection I
public void setBook(BookInterface book) {
this.book = book;
}
// injection II
public BookInterface setBook(String bookName) {
try {
Class<?> cl = Class.forName(bookName);
Constructor<?> constructor = cl.getConstructor(); // use it for parameters in constructor
BookInterface book = (BookInterface) constructor.newInstance();
//book = (BookInterface) Class.forName(bookName).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return book;
}
public BookInterface getBook() {
return book;
}
public static void main(String[] args) {
}
}
Les trois classes peuvent être masquées pour leur propre implémentation. Maintenant nous pouvons utiliser ce code pour DI:
package com.deepam.implement;
import com.deepam.hidden.Subscriber;
import com.deepam.hidden.FictionBook;
public class CallHiddenImplBook {
public CallHiddenImplBook() {
// TODO Auto-generated constructor stub
}
public void doIt() {
Subscriber ab = new Subscriber();
// injection I
FictionBook bookI = new FictionBook();
bookI.setHeight(30); // cm
bookI.setPages(250);
ab.setBook(bookI); // inject
System.out.println("injection I " + ab.getBook().toString());
// injection II
FictionBook bookII = ((FictionBook) ab.setBook("com.deepam.hidden.FictionBook")).setHeight(5).setPages(108); // inject and set
System.out.println("injection II " + ab.getBook().toString());
}
public static void main(String[] args) {
CallHiddenImplBook kh = new CallHiddenImplBook();
kh.doIt();
}
}
Il existe de nombreuses manières d'utiliser l'injection de dépendance. Il est possible de le combiner avec Singleton, etc., mais toujours en base, il n’ya qu’une association réalisée en créant un attribut de type objet à l’intérieur d’un autre objet . L’utilité n’est que et seulement en fonctionnalité, ce code, que nous devrions écrire encore et encore est toujours préparé et fait pour nous avant. C'est pourquoi DI est si étroitement liée à Inversion of Control (IoC), ce qui signifie que notre programme transmet au contrôle un autre module en cours d'exécution, qui effectue des injections de beans dans notre code. (Chaque objet pouvant être injecté peut être signé ou considéré comme un bean.) Par exemple, au printemps, cela se fait en créant et en initialisant ApplicationContext container, qui effectue ce travail pour nous. Dans notre code, nous créons simplement le contexte et invoquons l'initialisation des beans. A ce moment l'injection a été faite automatiquement.
de Book Apress.Spring.Persistence.with.Hibernate.Oct.2010
Le but de l'injection de dépendance est de découpler le travail de résolution de composants logiciels externes à partir de votre entreprise d’application logic.Sans injection de dépendance, les détails de la façon dont un composant Les accès aux services requis peuvent s’embrouiller avec le composant .__ du composant. code. Cela augmente non seulement le potentiel d’erreurs, ajoute le code gonfle et amplifie les complexités de la maintenance; il couple des composants ensemble plus étroitement, ce qui rend difficile de modifier les dépendances lorsque refactoring ou test.
En termes simples, l’injection de dépendance (ID) permet d’éliminer les dépendances ou les couplages étroits entre différents objets. L'injection de dépendance confère un comportement cohérent à chaque objet.
DI est la mise en œuvre de IOC - principal de Spring qui dit "Ne nous appelez pas, nous vous appellerons". L'utilisation du programmeur d'injection de dépendance n'a pas besoin de créer un objet en utilisant le nouveau mot-clé.
Les objets sont une fois chargés dans le conteneur Spring, puis nous les réutilisons chaque fois que nous en avons besoin en les récupérant à l'aide de la méthode getBean (String beanName).
L'injection de dépendance (ID) fait partie de la pratique du principe d'inversion de dépendance (DIP), également appelée Inversion of Control (IoC). Fondamentalement, vous devez utiliser DIP car vous voulez rendre votre code plus modulaire et testable à l'unité, au lieu d'un seul système monolithique. Vous commencez donc à identifier des parties du code qui peuvent être séparées de la classe et extraites de manière abstraite. Maintenant, l'implémentation de l'abstraction doit être injectée de l'extérieur de la classe. Normalement, cela peut être fait via le constructeur. Vous créez donc un constructeur qui accepte l’abstraction en tant que paramètre, il s’appelle injection de dépendance (via constructeur). Pour plus d'explications sur les conteneurs DIP, DI et IoC, vous pouvez lire ici
L’injection de dépendance est au cœur du concept associé à Spring Framework. Tout en créant la structure d’un projet, le printemps peut jouer un rôle vital. Dans ce cas, l’injection de dépendance se présente sous la forme d’un pichet.
En fait, supposons que vous ayez créé en Java deux classes différentes (classes A et B) et que, quelles que soient les fonctions disponibles en classe B, vous souhaitiez les utiliser en classe A, vous pouvez alors utiliser l'injection de dépendance crate objet d’une classe à l’autre, de la même manière que vous pouvez injecter une classe entière dans une autre classe pour la rendre accessible . De cette manière, la dépendance peut être surmontée.
INJECTION DE DEPENDANCE IS SIMPLEMENT COLLAGE DE DEUX CLASSES ET AT EN MEME TEMPS EN LES CONSERVANT SEPARES.
Je proposerais une définition légèrement différente, concise et précise de ce qu'est une dépendance injectable, en se concentrant sur l'objectif principal et non sur les moyens techniques (à partir de ici ):
L'injection de dépendance est le processus de création du statique, sans état graphe des objets de service, où chaque service est paramétré par son dépendances.
Les objets que nous créons dans nos applications (que nous utilisions Java, C # ou un autre langage orienté objet) appartiennent généralement à l'une des deux catégories suivantes: «objets de service» stateless, globaux et globaux, et stateful, dynamique et local. «Objets de données».
Le graphique de module - le graphique des objets de service - est généralement créé au démarrage de l'application. Cela peut être fait à l'aide d'un conteneur, tel que Spring, mais également manuellement, en passant des paramètres aux constructeurs d'objet. Les deux manières ont leurs avantages et leurs inconvénients, mais un cadre n’est certainement pas nécessaire pour utiliser l’ID dans votre application.
Une exigence est que les services doivent être paramétrés par leurs dépendances. Ce que cela signifie exactement dépend de la langue et de l'approche adoptées dans un système donné. Généralement, cela prend la forme de paramètres de constructeur, mais l’utilisation de setters est également une option. Cela signifie également que les dépendances d'un service sont masquées (lors de l'appel d'une méthode de service) aux utilisateurs du service.
Quand utiliser? Je dirais que chaque fois que l'application est suffisamment volumineuse pour que la logique soit encapsulée dans des modules séparés, un graphe de dépendance entre les modules procure un gain de lisibilité et d'exploration du code.
L'injection de dépendance est la pratique qui consiste à rendre agnostiques en composantes découplées à partir de certaines de leurs dépendances. Cette procédure est conforme à la directive SOLID qui dit
Principe de l’inversion de dépendance: il faut "dépendre des abstractions, pas des concrétions.
La meilleure implémentation de l’injection de dépendances est le modèle de conception Racine de composition, car il permet de découpler vos composants du conteneur d’injection de dépendances.
Je recommande cet excellent article sur Composition Root http://blog.ploeh.dk/2011/07/28/CompositionRoot/ Écrit par Mark Seemann
voici les points essentiels de cet article:
Une racine de composition est un emplacement (de préférence) unique dans une application où les modules sont composés ensemble.
...
Seules les applications doivent avoir des racines de composition. Bibliothèques et les cadres ne devraient pas.
...
Un conteneur DI ne doit être référencé qu'à partir de la racine de composition . Tous les autres modules ne doivent avoir aucune référence au conteneur.
La documentation de Di-Ninja, un framework d’injection de dépendance, est un très bon exemple pour démontrer le fonctionnement des principes de composition en racine et d’injection de dépendance . https://github.com/di-ninja/di-ninja Comme je le sais, est le seul DiC en javascript qui implémente le modèle de conception Composition-Root.
De Christoffer Noring, livre «Learning Angular - Second Edition» de Pablo Deeleman:
"Au fur et à mesure que nos applications grandissent et évoluent, chacune de nos entités de code nécessitera en interne des instances d'autres objets, qui sont mieux connus sous le nom de dépendances dans le monde du génie logiciel. Le fait de transmettre ces dépendances au client dépendant est appelé injection, et cela implique également la participation d'une autre entité de code, nommée l'injecteur, qui sera responsable de l'instanciation et de l'amorçage des dépendances requises afin qu'elles soient prêtes à être utilisées dès le moment où elles ont été injectées avec succès dans le client. le client ne sait pas comment instancier ses propres dépendances et ne connaît que l'interface qu'ils implémentent pour pouvoir les utiliser. "
L’injection de dépendance est un type d’application du principe " Inversion of Control " sur lequel est basé la construction de Frameworks.
Frameworks comme indiqué dans le "Schéma de conception" du GoF, sont des classes qui implémentent la logique de flux de contrôle principal, ce qui permet au développeur de le faire. Frameworks réalise ainsi l'inversion du principe de contrôle.
Une façon de mettre en œuvre en tant que technique, et non pas en tant que hiérarchie de classes, ce principe IoC, il s’agit simplement de Dependency Injection.
DIconsiste principalement à déléguer le mappage des instances de classes et une référence de type à ces instances, à une "entité" externe: un objet, une classe statique, un composant, un framework, etc ...
Les instances de classes sont les "dépendances", la liaison externe du composant appelant avec l'instance de classe par la référence, il s'agit du "injection".
Bien entendu, vous pouvez implémenter cette technique de différentes manières, du point de vue OOP, voir par exemple constructeur injection, setter injection, interface injection.
Déléguer un tiers pour exécuter la tâche d'association d'une référence à un objet est très utile lorsque vous souhaitez séparer complètement un composant nécessitant des services de la même implémentation.
De cette manière, lors de la conception de composants, vous pouvez vous concentrer exclusivement sur leur architecture et leur logique spécifique, en faisant confiance aux interfaces pour collaborer avec d'autres objets sans vous soucier des modifications d'implémentation des objets/services utilisés, même si vous utilisez le même objet sera totalement remplacé (en respectant évidemment l'interface).
Toute application non triviale est composée de deux classes ou plus qui collaborent pour exécuter une logique métier. Traditionnellement, chaque objet est responsable de l'obtention de ses propres références aux objets avec lesquels il collabore (ses dépendances). Lors de l'application de DI, les objets se voient attribuer leurs dépendances au moment de la création par une entité externe qui coordonne chaque objet du système. En d'autres termes, les dépendances sont injectées dans des objets.
Pour plus de détails, veuillez voir entrez la description du lien ici
DI est la manière dont les objets réels interagissent réellement les uns avec les autres sans qu'un objet soit responsable de l'existence d'un autre objet. Les objets doivent être traités de manière égale. Ils sont tous des objets. Personne ne devrait agir comme un créateur. C'est ainsi que vous rendez justice à vos objets.
Exemple simple :
si vous avez besoin d'un médecin, vous devez simplement en trouver un. Vous ne penserez pas à créer un médecin à partir de rien pour vous aider. Il existe déjà et il peut vous servir ou servir d'autres objets. Il a le droit d'exister, que vous (un seul objet) ayez besoin de lui ou non, car son but est de servir un ou plusieurs objets. Qui a décidé que son existence était Dieu tout-puissant, pas une sélection naturelle. Par conséquent, l’un des avantages de DI est d’éviter de créer des objets redondants inutiles et vivant sans but pendant la vie de votre univers (c’est-à-dire une application).