Qu'est-ce que l'injection de dépendance?

il y a eu plusieurs questions déjà affichées avec des questions spécifiques sur injection de dépendance , comme quand l'utiliser et quels cadres sont là pour elle. Toutefois,

qu'est-ce que l'injection de dépendance et quand/pourquoi devrait-elle ou ne devrait-elle pas être utilisée?

2696
demandé sur Peter Mortensen 2008-09-25 04:28:40

30 réponses

fondamentalement, au lieu d'avoir vos objets créant une dépendance ou demandant à un objet d'usine d'en faire une pour eux, vous passez les dépendances nécessaires à l'objet extérieurement, et vous en faites le problème de quelqu'un d'autre. Ce "quelqu'un" est soit un objet plus haut dans le graphe de dépendances, soit un injecteur de dépendances (framework) qui construit le graphe de dépendances. Une dépendance que j'utilise ici est tout autre objet à l'objet courant doit contenir une référence.

L'un des principaux avantages de l'injection de dépendances est qu'elle peut rendre les tests beaucoup plus faciles. Supposons que vous ayez un objet qui dans son constructeur fait quelque chose comme:

public SomeClass() {
    myObject = Factory.getObject();
}

cela peut être gênant quand tout ce que vous voulez faire est d'exécuter des tests unitaires sur une classe, surtout si myObject est quelque chose qui fait l'accès complexe au disque ou au réseau. Donc maintenant vous regardez se moquer de myObject, mais aussi intercepter l'appel de l'usine. Dur. Au lieu de cela, passez l'objet dans comme argument au constructeur. Maintenant vous avez déplacé le problème ailleurs, mais tester peut devenir beaucoup plus facile. Fais juste un objet factice et fais passer ça. Le constructeur ressemblerait maintenant un peu à:

public SomeClass (MyClass myObject) {
    this.myObject = myObject;
}

c'est un style d'injection de dépendance - via le constructeur. Plusieurs mécanismes sont possibles.

  • , Comme indiqué dans les commentaires, une alternative est de définir un constructeur, et avoir les dépendances injecté par l'intermédiaire de promoteurs immobiliers (h/t @MikeVella).
  • Martin Fowler documente une troisième alternative (h/t @MarcDix), où les classes implémentent explicitement une interface pour les dépendances qu'elles souhaitent injecter.

Lorsqu'ils n'utilisent pas l'injection de dépendance (comme dans les classes qui font trop de travail dans leurs constructeurs etc.), il devient de plus en plus difficile d'isoler les composants dans les essais unitaires.

retour en 2013 lorsque j'ai écrit cette réponse, il s'agissait d'un thème majeur sur le Google Testing Blog . Cela reste le plus grand avantage pour moi, car vous n'avez pas toujours besoin de la flexibilité supplémentaire dans votre conception de l'exécution (par exemple, pour le service Localisateur ou des modèles similaires), mais vous avez souvent besoin d'être en mesure d'isoler vos classes pendant les tests.

1680
répondu wds 2017-11-19 19:39:42

la meilleure définition que j'ai trouvée jusqu'à présent est one by James Shore :

"l'Injection de Dépendance" est à 25 dollars terme pour un concept à 5 cents. [...] L'injection de dépendance signifie donner une objet ses variables d'instance. [...].

il y a un article de Martin Fowler qui pourrait s'avérer utile, aussi.

L'injection de dépendance est essentiellement fournir les objets dont un objet a besoin (ses dépendances) au lieu de les construire lui-même. C'est une technique très utile pour tester, car elle permet de se moquer des dépendances.

Les dépendances

peuvent être injectées dans des objets par de nombreux moyens (comme l'injection du constructeur ou l'injection du setter). On peut même utiliser des structures d'injection de dépendances spécialisées (par exemple le ressort) pour faire cela, mais elles ne sont certainement pas nécessaires. Vous n'avez pas besoin de ces cadres avoir une injection de dépendance. Instancier et passer des objets (dépendances) explicitement est aussi bien une injection que l'injection par framework.

2097
répondu Thiago Arrais 2017-01-29 21:43:32

j'ai trouvé ce drôle d'exemple en termes de accouplement lâche :

toute application est composée de nombreux objets qui collaborent entre eux pour effectuer des choses utiles. Traditionnellement, chaque objet est responsable d'obtenir ses propres références aux objets dépendants (dépendances) avec lesquels il collabore. Cela conduit à des classes hautement couplées et à un code difficile à tester.

par exemple, considérez un objet Car .

A Car dépend des roues, du moteur, du carburant, de la batterie, etc. exécuter. Traditionnellement, nous définissons la marque de tels objets dépendants ainsi 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, le Car objet est responsable de la création des objets dépendants.

Que faire si nous voulons changer le type de son objet dépendant - dire Wheel - après les perforations initiales NepaliRubberWheel() ? Nous avons besoin de recréer l'objet de la voiture avec sa nouvelle dépendance dire ChineseRubberWheel() , mais seul le fabricant Car peut le faire.

alors qu'est-ce que le Dependency Injection nous faire...?

lors de l'utilisation de l'injection de dépendances, les objets sont donnés leurs dépendances à l'exécution plutôt que le temps de compilation (temps de fabrication de la voiture) . Pour que nous puissions changer le Wheel quand nous le voulons. Ici, le dependency ( wheel ) peut être injecté dans le Car au moment de l'exécution.

après injection de dépendance:

ici, nous sommes injection le dépendances (roue et batterie) au moment de 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;
  }
}

Source: la Compréhension de l'injection de dépendance

515
répondu gtiwari333 2018-06-10 05:42:12

L'Injection de dépendances est une pratique où les objets sont conçus d'une manière où ils reçoivent des instances des objets à partir 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 substitué sans changer le code, ce qui simplifie les tests et améliore le découplage.

par exemple, considérez ces clases:

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, la mise en œuvre de PersonService::addManager et PersonService::removeManager nécessiterait une instance du service de groupe pour faire son travail. Sans Injection de dépendance, la méthode traditionnelle serait d'instancier un nouveau GroupMembershipService dans le constructeur de PersonService et d'utiliser cet attribut d'instance dans les deux fonctions. Cependant, si le constructeur de GroupMembershipService a plusieurs choses dont il a besoin, ou pire encore, il y a quelques "setters" d'initialisation qui doivent être appelé GroupMembershipService , le code croît assez rapidement, et le PersonService ne dépend plus seulement du GroupMembershipService , mais aussi de tout ce dont dépend le GroupMembershipService . De plus, le lien avec GroupMembershipService est codé en dur dans le PersonService ce qui signifie que vous ne pouvez pas "simuler" un GroupMembershipService à des fins de test, ou d'utiliser un modèle de stratégie dans différentes parties de votre application.

avec Injection de dépendance, au lieu d'instancier le GroupMembershipService dans votre PersonService , youd soit passer dans le PersonService constructeur, ou bien ajouter une Propriété (getter et setter) pour définir une instance locale. Cela signifie que votre PersonService n'a plus à s'inquiéter de la façon de créer un GroupMembershipService , il accepte juste ceux qu'il est donné, et travaille avec eux. Cela signifie également que tout ce qui est une sous-classe de GroupMembershipService , ou met en œuvre l'interface GroupMembershipService peut être "injecté" dans le PersonService , et le PersonService n'a pas besoin de savoir le changement.

235
répondu Adam Ness 2017-11-19 19:44:36

la réponse acceptée est une bonne - mais je voudrais ajouter à cela que DI est très semblable à l'évitement Classique des constantes codées 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 et passez une variable contenant cette valeur à l'endroit où elle est nécessaire. La raison pour cela est que ces constantes généralement changent plus fréquemment que le reste du code. Pour 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 ici au lieu de littérales constantes sont des objets entiers - mais la raison de déplacer le code qui les crée à partir du code de classe est similaire - les objets changent plus fréquemment que le code qui les utilise. Un cas important où un tel changement est nécessaire que les tests.

144
répondu zby 2011-01-06 18:33:39

imaginons que vous vouliez aller à la pêche:

  • Sans injection de dépendance, vous devez prendre soin 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 ça te donne beaucoup de responsabilités. En termes de logiciel, cela signifie que vous devez effectuer une recherche pour toutes ces choses.

  • avec injection de dépendance, quelqu'un else s'occupe de toute la préparation et met l'équipement nécessaire à votre disposition. Vous recevrez ("injecté"), le bateau, la canne à pêche et les appâts prêts à l'utilisation.

98
répondu Olivier Liechti 2014-01-27 23:01:49

essayons exemple simple avec voiture et moteur classes, toute voiture a besoin d'un moteur pour aller n'importe où, au moins pour l'instant. Donc, ci-dessous comment le code aura l'air 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 de voiture 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 en ElectricityEngine alors nous aurons besoin de réécrire classe de Voiture. Et plus l'application est grande, 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 est que notre classe de haut niveau de voiture dépend de la classe de niveau inférieur de Gazengine qui violent le principe D'Inversion de dépendance(DIP) de solide. DIP suggère que nous devrions dépendre d'abstractions, pas de classes concrètes. Donc pour satisfaire ceci nous introduisons iengine interface et réécrire 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 de voiture dépend uniquement de l'interface IEngine, pas une implémentation spécifique du moteur. Maintenant, le seul truc c'est comment créer une instance de la voiture et lui donner une vraie classe de moteur en béton comme le GasEngine ou le 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 du moteur) au constructeur automobile. Donc 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 de voiture.

le principal avantage de La l'Injection de Dépendance que les classes sont plus faiblement couplés, parce qu'ils n'ont pas codé en dur dépendances. Ceci suit le principe de L'Inversion de dépendance, qui a été mentionné ci-dessus. Au lieu de renvoyer à des implémentations spécifiques, les classes demandent des abstractions (habituellement interfaces ) qui leur sont fournies lors de la construction de la classe.

Donc à la fin l'injection de Dépendance est juste 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 la classe a besoin dans afin d'effectuer ses actions, les dépendances sont fournis à la classe (le plus souvent) par injection du constructeur.

aussi quand nous avons beaucoup de dépendances, il est très bon d'utiliser des conteneurs D'Inversion de contrôle(IoC) que nous pouvons dire quelles interfaces devraient être mappées à quelles implémentations concrètes pour toutes nos dépendances et nous pouvons lui faire résoudre ces dépendances pour nous quand il construit notre objet. Par exemple, nous pourrions spécifier dans la cartographie pour le conteneur IoC que la dépendance IEngine devrait être mappée à la dépendance GasEngine classe et quand nous demandons au conteneur du CIO pour une instance de notre voiture classe, il construira automatiquement notre voiture classe avec un Gazengine dépendance passée dans.

mise à JOUR: Regardé cours sur EF Base de Julie Lerman récemment et aussi aimé sa courte définition sur DI.

injection de dépendance est un modèle pour permettre à votre application d'injecter objets à la volée à des classes qui en ont besoin, sans forcer ceux les classes seront responsables de ces objets. Il permet à votre code plus vaguement couplé, et le noyau du cadre de L'entité se branche à ce même système de services.

84
répondu user2771704 2017-11-19 19:44:45

Ce est la plus simple explication à propos de l'Injection de Dépendance et Conteneur d'Injection de Dépendance j'ai jamais vu:

Sans Injection De Dépendance

  • aux besoins de l'Application Foo (par exemple, un contrôleur), donc:
  • Application crée Foo
  • Application appelle Foo
    • Foo Bar besoins (par exemple un service), ainsi:
    • Toto crée Bar
    • Foo calls Bar
      • Bar besoins Bim (un service, un référentiel, ...), donc:
      • Bar crée Bim
      • Barre " fait quelque chose

Avec Injection De Dépendance

  • aux besoins de l'Application Foo, qui a besoin de Bar, qui doit Bim, so:
  • Application crée Bim
  • Application crée un Bar et lui donne Bim
  • Application crée Toto et lui donne un Bar
  • Application appelle Foo
    • Foo appels Bar
      • Barre " fait quelque chose

utilisant un récipient D'Injection de dépendance

  • aux besoins de l'Application Foo:
  • Application obtient Foo du conteneur, donc:
    • Conteneur crée Bim
    • conteneur crée Bar et lui donne Bim
    • Conteneur crée Toto et lui donne un Bar
  • Application appelle Foo
    • Foo appels Bar
      • Barre " fait quelque chose

l'Injection de Dépendance et l'Injection de dépendance Conteneurs sont des choses différentes:

  • l'Injection de Dépendance est une méthode pour l'écriture d'un code de meilleure qualité
  • un conteneur DI est un outil pour aider à l'injection de dépendances

vous n'avez pas besoin d'un récipient pour faire une injection de dépendance. Cependant, un contenant peut vous aider.

82
répondu Trix 2016-09-21 09:37:42

"injection de dépendance" ne signifie-t-il pas simplement utiliser des constructeurs paramétrés et des setters publics?

James Shore article montre les exemples suivants à des fins de 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(); 
    ... 
  } 
}
46
répondu JaneGoodall 2017-11-19 19:45:01

Qu'est-ce que L'Injection de dépendance (ai)?

comme d'autres l'ont dit, Dependency Injection(DI) supprime la responsabilité de la création directe, et de la gestion de la durée de vie, d'autres instances d'objet sur lesquelles notre classe d'intérêt (classe de consommation) dépend (dans le UML sens ). Ces instances sont plutôt passées à notre classe de consommateurs, typiquement sous forme de paramètres de constructeur ou via setters de propriété (la gestion de l'instanciation d'objet de dépendance et le passage à la classe de consommateur est habituellement effectuée par un Inversion de contrôle (IoC) conteneur, mais c'est un autre sujet).

DI, DIP and SOLID

spécifiquement, dans le paradigme de Robert C Martin SOLID principles of Object Oriented Design , DI est l'un des possibles les implémentations de la Inversion de la Dépendance Principe (DIP) . Le DIP est le D du SOLID mantra - d'autres implémentations DIP incluent le Localisateur de Service, et les modèles de Plugin.

l'Objectif du DIP est de découpler les dépendances étroites et concrètes entre les classes, et au lieu de cela, de desserrer l'assemblage au moyen d'une abstraction, qui peut être réalisée via un interface , abstract class ou pure virtual class , selon le langage et l'approche utilisés.

sans le DIP, notre code (j'ai appelé cette "classe consommatrice") est directement couplé à une dépendance concrète et est souvent chargé de la responsabilité de savoir comment obtenir, et gérer, une instance de cette dépendance, c'est-à-dire conceptuellement:

"I need to create/use a Foo and invoke method `GetBar()`"

attendu Qu'après L'application de L'immersion, l'exigence est assouplie, et la préoccupation d'obtenir et de gérer la durée de vie de la dépendance Foo a été supprimée:

"I need to invoke something which offers `GetBar()`"

Pourquoi utiliser DIP (and DI)?

découplage des dépendances entre classes permet ainsi substitution facile de ces classes de dépendances avec d'autres implémentations qui remplissent également les pré-requis de l'abstraction (par exemple la dépendance peut être commutée avec une autre implémentation de la même interface). En outre, comme d'autres l'ont mentionné, peut-être la la raison la plus courante de découpler les classes via le DIP est de permettre à une classe consommatrice d'être testée isolément, car ces mêmes dépendances peuvent maintenant être entaillées et/ou moquées.

une conséquence de DI est que la gestion de la durée de vie des instances d'objets de dépendance n'est plus contrôlée par une classe de consommation, puisque l'objet de dépendance est maintenant passé dans la classe de consommation (via le constructeur ou le setter injection.)

cela peut être vu de différentes façons:

  • si le contrôle de la durée de vie des dépendances par la classe consommatrice doit être maintenu, le contrôle peut être rétabli en injectant une usine (abstraite) pour créer les instances de la classe de dépendance, dans la classe consommatrice. Le consommateur sera en mesure d'obtenir des instances via un Create sur l'usine si nécessaire, et disposer de ces instances une fois terminée.
  • ou, le contrôle de la durée de vie des instances de dépendance peut être cédé à un conteneur IoC (plus d'informations à ce sujet ci-dessous).

quand utiliser DI?

  • où il sera probablement nécessaire de substituer une dépendance à une mise en œuvre équivalente,
  • chaque fois que vous aurez besoin d'unité tester les méthodes d'une classe dans l'isolement de ses dépendances,
  • où l'incertitude de la durée de vie d'une dépendance peut justifier l'expérimentation (par exemple, MyDepClass est filé sûr - que faire si nous en faisons un seul et injectons la même instance dans tous les consommateurs?)

exemple

voici un simple c # implémentation. Compte tenu de la classe de consommation ci-dessous:

public class MyLogger
{
   public void LogRecord(string somethingToLog)
   {
      Console.WriteLine("{0:HH:mm:ss} - {1}", DateTime.Now, somethingToLog);
   }
}

bien qu'apparemment inoffensif, il a deux static les dépendances sur deux autres classes, System.DateTime et System.Console , qui non seulement limitent les options de sortie de journalisation (journalisation sur console sera sans valeur si personne ne regarde), mais pire, il est difficile de tester automatiquement compte tenu de la dépendance sur une horloge de système non déterministe.

nous pouvons cependant appliquer DIP à cette classe, en faisant abstraction de la préoccupation de timestamping comme une dépendance, et de couplage MyLogger seulement à une interface simple:

public interface IClock
{
    DateTime Now { get; }
}

nous pouvons aussi relâcher la dépendance sur Console à une abstraction, comme un TextWriter . L'Injection de dépendances est généralement implémentée sous la forme d'une injection constructor (passant une abstraction à une dépendance comme paramètre au constructeur d'une classe consommatrice) ou Setter Injection (passant la dépendance via un setter setXyz() ou une propriété .Net avec {set;} définie). L'Injection par le constructeur est préférée, car elle garantit class sera dans un état correct après construction, et permet aux champs de dépendances internes d'être marqués comme readonly (C#) ou final (Java). Donc en utilisant l'injection du constructeur sur l'exemple ci-dessus, cela nous laisse avec:

public class MyLogger : ILogger // Others will depend on our logger.
{
    private readonly TextWriter _output;
    private readonly IClock _clock;

    // Dependencies are injected through the constructor
    public MyLogger(TextWriter stream, IClock clock)
    {
        _output = stream;
        _clock = clock;
    }

    public void LogRecord(string somethingToLog)
    {
        // We can now use our dependencies through the abstraction 
        // and without knowledge of the lifespans of the dependencies
        _output.Write("{0:yyyy-MM-dd HH:mm:ss} - {1}", _clock.Now, somethingToLog);
    }
}

(un béton Clock doit être fourni, qui pourrait bien sûr revenir à DateTime.Now , et les deux dépendances doivent être fournies par un conteneur IoC via injection du constructeur)

An un test D'Unité automatisé peut être construit, ce qui prouve définitivement que notre logger fonctionne correctement, car nous avons maintenant le contrôle sur les dépendances - le temps, et nous pouvons espionner sur la sortie écrite:

[Test]
public void LoggingMustRecordAllInformationAndStampTheTime()
{
    // Arrange
    var mockClock = new Mock<IClock>();
    mockClock.Setup(c => c.Now).Returns(new DateTime(2015, 4, 11, 12, 31, 45));
    var fakeConsole = new StringWriter();

    // Act
    new MyLogger(fakeConsole, mockClock.Object)
        .LogRecord("Foo");

    // Assert
    Assert.AreEqual("2015-04-11 12:31:45 - Foo", fakeConsole.ToString());
}

Prochaines Étapes

injection de dépendance est invariablement associée à une Inversion du conteneur de contrôle (IoC) , pour injecter (fournir) les instances de dépendance concrètes, et pour gérer les instances de durée de vie. Pendant le processus de configuration/ bootstrapping ,les conteneurs IoC permettent de définir ce qui suit:

  • cartographie entre chaque abstraction et la mise en œuvre concrète configurée (par exemple " chaque fois qu'un consommateur demande un IBar , retourner un ConcreteBar instance )
  • Des politiques
  • peuvent être établies pour la gestion de la durée de vie de chaque dépendance, par exemple pour créer un nouvel objet pour chaque instance de consommateur, pour partager une instance de dépendance unique parmi tous les consommateurs, pour partager la même instance de dépendance uniquement à travers le même fil, etc.
  • dans .Net, les conteneurs IoC sont au courant de protocoles tels que IDisposable et prendront la responsabilité de Disposing dépendances en ligne avec la gestion de durée de vie configurée.

typiquement, une fois que les conteneurs IoC ont été configurés/ démarrés, ils fonctionnent en arrière-plan, permettant au codeur de se concentrer sur le code en question plutôt que de s'inquiéter des dépendances.

la clé du Code DI-friendly est d'éviter le couplage statique des classes, et de ne pas utiliser new () pour la création de dépendances

comme dans l'exemple ci-dessus, le découplage des dépendances exige un certain effort de conception, et pour le développeur, il y a un changement de paradigme nécessaire pour briser l'habitude de new dépendences ing directement,et au lieu de faire confiance au conteneur pour gérer les dépendances.

mais les avantages sont nombreux, surtout dans la capacité de tester à fond votre classe d'intérêt.

Note : La création / cartographie / projection (via new ..() ) de POCO / POJO / de Sérialisation Dto / Entité Graphiques / Anonyme JSON projections et al - dire des Données "seulement" des classes ou des enregistrements ou retourné à partir de les méthodes sont et non considérées comme des dépendances (au sens de L'UML) et non assujetties à L'ai. Utiliser new pour les projeter est très bien.

34
répondu StuartLC 2017-05-23 11:33:24

pour rendre le concept D'Injection de dépendance simple à comprendre. Prenons un exemple de bouton d'interrupteur pour basculer (on/off) une ampoule.

Sans Injection De Dépendance

Le commutateur

doit savoir à l'avance à quelle ampoule je suis connecté (dépendance à code dur). So,

Switch -> PermanentBulb //switch est connecté directement à un permanent de l'ampoule, contrôle qui n'est pas possible facilement

Switch(){
PermanentBulb = new Bulb();
PermanentBulb.Toggle();
}

Avec Injection De Dépendance

L'interrupteur

sait seulement que je dois allumer/éteindre l'ampoule qui m'est passée. So,

Switch - > Bulb1 OR Bulb2 OR NightBulb (injected dependency) ""

Switch(AnyBulb){ //pass it whichever bulb you like
AnyBulb.Toggle();
}

modifiant 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(); 
    ... 
  } 
}`
31
répondu wakqasahmed 2016-10-29 08:23:57

le point entier de L'Injection de dépendance (DI) est de garder le code source de l'application propre et stable :

  • propre de la dépendance de code d'initialisation
  • stable indépendamment de la dépendance utilisée

pratiquement, chaque motif de conception sépare les préoccupations de faire des changements futurs affecter nombre minimum de fichiers.

le domaine spécifique de DI est la délégation de configuration et d'initialisation de dépendances.

exemple: DI avec script shell

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).

Consider simple dependent.sh script:

#!/bin/sh
# Dependent
touch         "one.txt" "two.txt"
archive_files "one.txt" "two.txt"

le script est dépendant: il ne s'exécute pas seul ( archive_files n'est pas défini).

vous définissez archive_files dans archive_files_zip.sh script d'implémentation (en utilisant zip dans ce cas):

#!/bin/sh
# Dependency
function archive_files {
    zip files.zip "$@"
}

au lieu de source - ing implementation script directement dans le dépendant, vous utilisez un injector.sh "conteneur" qui enveloppe les deux "composants":

#!/bin/sh 
# Injector
source ./archive_files_zip.sh
source ./dependent.sh

le archive_files dépendance vient de injecté en dépendant "1519520920 de script".

vous auriez pu injecter la dépendance qui implémente archive_files en utilisant tar ou xz .

exemple: suppression de DI

si le script dependent.sh utilisait directement les dépendances, l'approche s'appellerait recherche de dépendances (qui est l'opposé de 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 lui-même l'initialisation.

le code source du "component" n'est ni clean ni stable parce que chaque changement dans l'initialisation des dépendances nécessite également une nouvelle version pour le fichier de code source de "components".

Derniers mots

DI n'est pas aussi largement souligné et popularisé que dans les cadres Java.

Mais c'est une approche générique pour diviser les préoccupations de:

  • application développement ( unique code source de la libération du cycle de vie)
  • application déploiement ( multiple environnements cibles avec cycles de vie indépendants)

utiliser la configuration uniquement avec recherche de dépendances n'aide pas car le nombre de paramètres de configuration peut changer par dépendance (par exemple, nouveau type d'authentification) ainsi que le nombre de types de dépendances pris en charge (par exemple, nouveau type de base de données).

23
répondu uvsmtid 2015-09-25 17:56:53

Qu'est-ce que l'Injection de dépendance?

injection de dépendance (DI) signifie découpler les objets qui sont dépendants les uns des autres. Dire d'Un objet dépend de l'Objet B si l'idée est de dissocier ces objets les uns des autres. Nous n'avons pas besoin de coder l'objet en utilisant un nouveau mot-clé plutôt que de partager des dépendances avec des objets à l'exécution malgré le temps de compilation. Si nous parlons de

Comment l'Injection de Dépendance travaux au Printemps:

nous n'avons pas besoin de code dur l'objet en utilisant un nouveau mot-clé plutôt que de définir la dépendance bean dans le fichier de configuration. Le printemps conteneur sera responsable de l'accrochage.

Inversion de la commande (IOC)

la COI est un concept général qui peut s'exprimer de différentes façons et L'Injection de dépendance est un exemple concret de la COI.

deux types D'Injection de dépendance:

  1. Constructeur D'Injection
  2. Injection Par Mutateur

1. Injection de dépendance basée sur le constructeur:

di basée sur le constructeur est accomplie quand le conteneur invoque un constructeur de classe avec un certain nombre d'arguments, chacun représentant une dépendance à l'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>

2. Injection de dépendance à base de Setter:

DI basé sur Setter est accompli par le conteneur appelant les méthodes de setter sur vos haricots après avoir invoqué un constructeur no-argument ou no-argument méthode usine statique pour instancier votre haricot.

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"/>

NOTE: C'est une bonne règle empirique d'utiliser des arguments de constructeur pour les dépendances obligatoires et des setters pour les dépendances optionnelles. Notez que le si nous utilisons l'annotation basée sur @Required annotation sur un setter peut être utilisé pour faire des setters comme des dépendances requises.

17
répondu Harleen 2016-03-05 09:46:56

la meilleure analogie à laquelle je puisse penser est le chirurgien et son(ses) assistant (s) dans une salle d'opération, où le chirurgien est la Personne principale et son assistant qui fournit les différents composants chirurgicaux quand il en a besoin afin que le chirurgien puisse se concentrer sur la seule chose qu'il fait le mieux (chirurgie). Sans l'assistant, le chirurgien doit récupérer les composants lui-même à chaque fois qu'il en a besoin.

DI En bref, est une technique pour supprimer une responsabilité supplémentaire commune (charge) sur les composants à récupérer les composants dépendants, en offrant à elle.

DI vous rapproche du principe de Responsabilité Unique (RS), comme le surgeon who can concentrate on surgery .

quand utiliser DI: je recommande D'utiliser DI dans presque tous les projets de production (petits / grands), en particulier dans les environnements d'affaires en constante évolution:)

pourquoi: parce que vous voulez que votre code soit facilement testable, mockable etc afin que vous puissiez tester rapidement vos modifications et les pousser vers le marché. En outre, pourquoi ne le feriez-vous pas lorsque vous Il ya beaucoup d'outils/cadres gratuits géniaux pour vous soutenir dans votre voyage à une base de codes où vous avez plus de contrôle.

15
répondu Anwar Husain 2016-04-05 16:15:55

toutes les réponses ci-dessus sont bonnes, mon but est d'expliquer le concept d'une manière simple afin que quiconque sans connaissance de programmation peut également comprendre le concept

L'injection de dépendance est l'un des modèles qui nous aident à créer des systèmes complexes d'une manière plus simple.

nous pouvons voir une grande variété d'application de ce modèle dans notre vie quotidienne. Certains des exemples sont Magnétophone, VCD, lecteur de CD etc.

Reel-to-reel portable tape recorder, mid-20th century.

l'image ci-dessus est celle d'un magnétophone portatif, datant du milieu du XXe siècle. Source .

le but premier d'un magnétophone est d'enregistrer ou de lire le son.Lors de la conception d'un système, il faut une bobine pour enregistrer ou lire le son ou la musique. nous pouvons placer la bobine à l'intérieur de la machine, ou bien nous pouvons fournir un crochet pour la bobine où elle peut être placée.si nous optons pour le deuxième qui place un crochet pour la bobine, nous obtenons un avantage supplémentaire de jouer n'importe quelle musique en changeant la bobine. et aussi la réduction de la fonction jouant n'importe quoi dans la bobine.

les principaux avantages que nous avons obtenus en utilisant l'injection de dépendance.

  • une Forte cohésion et le couplage lâche.
  • de l'externalisation de la dépendance et de la recherche que sur la responsabilité.
  • faire des choses comme des composants et de se combiner pour former un grand système avec des capacités élevées.
  • il aide à développer des composants de haute qualité puisqu'ils sont développés indépendamment ils sont correctement testés.
  • il est utile de remplacer le composant par un autre en cas de défaillance de l'un d'eux.

de nos jours, ce concept constitue la base de cadres bien connus dans le monde de la programmation. L'angle du ressort etc sont les cadres logiciels bien connus construits sur le dessus de ce concept

injection de dépendances est un modèle utilisé pour créer des instances d'objets sur lesquels d'autres objets se fient sans savoir au moment de la compilation quelle classe sera utilisée pour fournir cette fonctionnalité ou simplement la façon d'injecter des propriétés à un objet est appelé injection de dépendances.

exemple d'injection de dépendance

nous sommes code d'écriture comme ceci

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 injection de dépendance, l'injecteur de dépendance décollera 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

14
répondu Samuel J Mathew 2017-12-20 03:35:12

cela signifie que les objets ne doivent avoir qu'autant de dépendances que nécessaire pour faire leur travail et que les dépendances doivent être peu nombreuses. De plus, les dépendances d'un objet devraient être basées sur des interfaces et non sur des objets "concrets", dans la mesure du possible. (Un objet concret est un objet créé avec le mot-clé new.) L'accouplement lâche favorise une plus grande réutilisabilité, une maintenabilité plus facile, et vous permet de fournir facilement des objets "simulés" à la place de services coûteux.

le "Injection de dépendance "(DI) est également connu sous le nom de" Inversion de contrôle " (IoC), peut être utilisé comme une technique pour encourager ce couplage lâche.

il y a deux approches principales à la mise en œuvre de L'ai:

  1. injection du constructeur
  2. injection par Mutateur

Constructeur d'injection

c'est la technique de passer des dépendances d'objets à son constructeur.

noter que le constructeur accepte une interface et non un objet concret. Notez également qu'une exception est lancée si le paramètre orderDao est null. Cela souligne l'importance de recevoir une dépendance valide. L'Injection par le constructeur est, à mon avis, le mécanisme préféré pour donner à un objet ses dépendances. Il est clair pour le développeur lors de l'invocation de l'objet quelles dépendances doivent être données à l'objet "Person" pour une exécution correcte.

Setter Injection

mais considérez l'exemple suivant... supposez que vous ayez une classe avec dix méthodes qui n'ont pas de dépendances, mais vous ajoutez une nouvelle méthode qui a une dépendance sur IDAO. Vous pouvez changer le constructeur pour utiliser L'Injection du constructeur, mais cela peut vous forcer à changer tous les appels du constructeur partout. Alternativement, vous pouvez simplement ajouter un nouveau constructeur qui prend la dépendance, mais alors comment un développeur facilement savoir quand utiliser l'un constructeur sur l'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? "Setter Injection" est une autre technique DI qui peut être utilisée dans des situations comme celle-ci.

Setter Injection ne force pas les dépendances à passer 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 indiqué précédemment, les principaux facteurs de motivation pour ce faire comprennent:

  1. le Soutien de l'injection de dépendance, sans avoir à modifier le constructeur de l'héritage de classe.
  2. permettant de créer des ressources ou des services coûteux aussi tard que possible et uniquement en cas de besoin.

Voici l'exemple du code ci-dessus:

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;
13
répondu Piyush Deshpande 2015-12-09 19:54:48

je pense que puisque tout le monde a écrit Pour DI, laissez-moi poser quelques questions..

  1. lorsque vous avez une configuration de DI où toutes les implémentations réelles(pas les interfaces) qui vont être injectées dans une classe (pour E. g services à un contrôleur) pourquoi n'est-ce pas une sorte de codage dur?
  2. Que faire si je veux changer l'objet à l'exécution? Par exemple, ma configuration dit déjà quand j'instancie MyController, injecter pour FileLogger comme ILogger. Mais je voudrais peut-être injecter DatabaseLogger.
  3. chaque fois que je veux changer les objets dont mon AClass a besoin, je dois maintenant regarder en deux endroits - la classe elle-même et le fichier de configuration. Comment rendre la vie plus facile?
  4. si la propriété D'AClass n'est pas injectée, est-il plus difficile de s'en débarrasser?
  5. pour revenir à la première question. Si Utiliser new object () est mauvais, pourquoi injecter l'implémentation et non l'interface? Je pense que beaucoup d'entre vous disent que nous injectons en fait l'interface mais la configuration vous fait spécifier l'implémentation de cette interface ..pas au moment de l'exécution .. il est codé en dur lors de la compilation.

C'est basé sur la réponse @Adam n posté.

pourquoi PersonService n'a-t-il plus à se soucier du service des membres de groupe? Vous venez de mentionner que GroupMembership a plusieurs choses(objets/propriétés) dont il dépend. Si GMService était requis dans PService, vous l'auriez comme propriété. Vous pouvez vous moquer de ça, que vous l'ayez injecté ou non. La seule fois où je voudrais qu'il soit injecté, C'est si GMService avait des classes d'enfants plus spécifiques, ce que vous ne sauriez pas avant l'exécution. Alors vous devriez injecter la sous-classe. Ou si vous vouliez utiliser ça comme un simple ou un prototype. Pour être honnête, le fichier de configuration a tout en dur jusqu'à quelle sous-classe pour un type (interface) il va injecter au cours de la compilation.

MODIFIER

Un gentil commentaire par Jose Maria Arranz sur DI

DI augmente la cohésion en éliminant tout besoin de déterminer la direction de la dépendance et d'écrire n'importe quel code de 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 annotation. XML et les annotations sont du code source.

DI réduit l'accouplement en rendant tous vos composants modulaires (c'est-à-dire remplaçables) et ont des interfaces bien définies entre eux.

faux. Vous n'avez pas besoin d'un cadre DI pour construire un code modulaire basé sur des interfaces.

à propos de remplaçable: avec un très simple .archive des propriétés et classe.forName vous pouvez définir quelles classes peuvent changer. Si TOUTE la classe de votre code peut être modifié, Java n'est pas pour vous, utilisez un langage de script. Soit dit en passant: les annotations ne peuvent pas être modifiées sans recompiler.

à mon avis, il n'y a qu'une seule raison pour les cadres DI: La réduction de la plaque de 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 cadre DI préféré, cadres DI promettent la réduction du code (XML et annotations sont aussi du code source). Le problème est que cette réduction de la plaque de chaudière est juste réel dans des cas très très 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 facile que de mapper une classe à un objet singleton.

10
répondu Chookoos 2014-07-11 00:26:51

Dependency Injection means a way (actually any-way ) for one part of code (E. g une classe) pour avoir accès aux dépendances (autres parties du code, E. g d'autres classes, cela dépend de) d'une manière modulaire sans qu'ils soient codés en dur (de sorte qu'ils puissent changer OU être modifiés librement, ou même être chargés à un autre moment, selon les besoins)

(et le ps , oui, c'est devenu trop hype 25$ nom pour une plutôt simple, concept) , mon .25 cents

8
répondu Nikos M. 2015-12-10 15:50:06

je sais qu'il y a déjà beaucoup de réponses, mais j'ai trouvé cela très utile: http://tutorials.jenkov.com/dependency-injection/index.html

Pas De 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)
  {...}

}

remarquez comment l'instanciation DataSourceImpl est déplacée dans un constructeur. Le constructeur prend quatre paramètres qui sont les quatre valeurs requises par la DataSourceImpl . Bien que le MyDao la classe dépend encore 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 .

7
répondu Ali Issa 2015-01-15 13:07:07

les réponses populaires sont inutiles, car elles définissent l'injection de dépendance d'une manière qui n'est pas utile. Convenons 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 cela passer des paramètres dans le constructeur. Nous avons fais régulièrement depuis que les constructeurs ont été inventés.

" dépendance l'injection" est considérée comme un type d ' "inversion de contrôle", ce qui signifie qu'une certaine logique est retirée de l'interlocuteur. Ce n'est pas le cas lorsque l'appelant passe en paramètres, donc si C'était DI, DI n'impliquerait pas une inversion de contrôle.

DI signifie qu'il y a 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épendances. Le "demandeur" est la personne tapant "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 il fait un

gcc -c foo.cpp; gcc -c bar.cpp

avant de faire un

gcc foo.o bar.o -o bar

la personne tapant" 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.

le but principal du niveau intermédiaire n'est pas seulement de passer dans les dépendances au constructeur, mais d'énumérer toutes les dépendances dans juste un endroit , et de les cacher du codeur (ne pas les faire fournir par le codeur).

habituellement, le niveau intermédiaire fournit des usines pour les objets construits, qui doivent fournir un rôle que chaque type d'objet demandé doit satisfaire. C'est parce qu'en ayant un niveau intermédiaire qui cache les détails de la construction, vous avez déjà encouru la pénalité d'abstraction imposée par les usines, donc vous pourriez aussi bien utiliser les usines.

7
répondu Phil Goetz 2015-06-02 18:32:45

L'injection de dépendance est une solution possible à ce que l'on pourrait généralement appeler l'exigence de l ' "obstruction de dépendance". L'obscurcissement de la dépendance est une méthode qui consiste à retirer la nature "évidente" du processus consistant à fournir une dépendance à une classe qui en a besoin et, par conséquent, à obscurcir, d'une manière ou d'une autre, la fourniture de ladite dépendance à ladite classe. Ce n'est pas nécessairement une mauvaise chose. En fait, en obscurcissant la façon dont une dépendance est fournie à une classe, alors quelque chose en dehors de la classe est responsable de créer la dépendance qui signifie, dans divers scénarios, une implémentation différente de la dépendance peut être fournie à la classe sans apporter de changements à la classe. C'est idéal pour passer d'un mode de production à un mode d'essai (par ex., en utilisant une dépendance de service "simulée").

malheureusement, la mauvaise partie est que certaines personnes ont supposé que vous avez besoin d'un cadre spécialisé pour faire l'obscurcissement de la dépendance et que vous êtes en quelque sorte "moindre" programmeur si vous choisissez de ne pas utiliser un cadre particulier pour le faire. Un autre mythe, extrêmement troublant, que beaucoup croient, est que l'injection de dépendance est le seul moyen de parvenir à l'obscurcissement de la dépendance. Ceci est manifestement et historiquement et évidemment faux à 100%, mais vous aurez du mal à convaincre certaines personnes qu'il y a des alternatives à l'injection de dépendance pour vos besoins d'obscurcissement de dépendance.

programmeurs ont compris la dépendance nécessité d'obfuscation depuis des années et de nombreuses solutions alternatives ont évolué avant et après l'injection de dépendance a été conçu. Il y a des motifs D'usine mais il y a aussi beaucoup d'options utilisant ThreadLocal où aucune injection à une instance particulière n'est nécessaire - la dépendance est effectivement injectée dans le thread qui a l'avantage de rendre l'objet disponible (via des méthodes de getter statiques de commodité) à n'importe quelle classe qui l'exige sans avoir à ajouter annotations aux classes qui l'exigent et mise en place complexe XML 'glue' pour y arriver. Lorsque vos dépendances sont requises pour la persistance (JPA/JDO ou autre), cela vous permet d'atteindre la "persistance tranaparente" beaucoup plus facilement et avec des classes de modèles de domaine et de modèles d'affaires composées uniquement de POJOs (c.-à-d. sans cadre spécifique/verrouillé dans les annotations).

6
répondu Volksman 2014-04-01 23:39:16

du Livre", le Bien-fondé de Développeur Java: l'Essentiel des techniques de Java 7 et polyglotte de la programmation

DI est une forme particulière de Cio, où le processus de trouver vos dépendances est en dehors du contrôle direct de votre code en cours d'exécution.

5
répondu TastyCode 2013-05-18 19:27:31

exemple, nous avons 2 classes Client et Service . Client utilisera Service

public class Service {
    public void doSomeThingInService() {
        // ...
    }
}

Sans Injection De Dépendance

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();
    }
}

3)

public class Client {
    Service service;
    public Client() {
        service = new Service();
    }
    public void doSomeThingInClient() {
        service.doSomeThingInService();
    }
}

1) 2) 3) Utilisation

Client client = new Client();
client.doSomeThingInService();

avantages

  • Simple

désavantages

  • Dur pour le test Client classe
  • quand nous changeons Service constructeur, nous devons changer le code dans tout lieu créer Service objet

utiliser Injection De Dépendance

voie 1) injection du 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();
    }
}

utilisant

Client client = new Client(new Service());
// Client client = new Client(new Service(), new SqliteDatabase());
client.doSomeThingInClient();

voie 2) injection de Setter

public class Client {
    Service service;

    public void setService(Service service) {
        this.service = service;
    }

    public void doSomeThingInClient() {
        service.doSomeThingInService();
    }
}

utilisant

Client client = new Client();
client.setService(new Service());
client.doSomeThingInClient();

voie 3) Interface injection

Check https://en.wikipedia.org/wiki/Dependency_injection

= = =

maintenant, ce code est déjà suivi de Dependency Injection et il est plus facile pour le test Client classe.

Cependant, nous utilisons encore new Service() beaucoup de temps et il n'est pas bon quand changer Service constructeur. Pour la prévenir, nous pouvons utiliser di injecteur 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(...));
    }
}

utilisant

Service service = Injector.provideService();

2) Utiliser bibliothèque: pour Android dagger2

avantages

  • Faire des test plus facile
  • lorsque vous changez le Service , vous avez seulement besoin de le changer dans la classe D'injecteur
  • si vous utilisez Constructor Injection , lorsque vous regardez le constructeur de Client , vous verrez combien de dépendance Client classe

désavantages

  • si vous utilisez l'utilisation Constructor Injection , l'objet Service est créé lorsque Client créé, parfois nous utilisons la fonction dans Client classe sans utilisation Service ainsi créé Service est gaspillé

injection de dépendance définition

https://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'utilisent

5
répondu Phan Van Linh 2018-08-14 08:32:32

à partir du Livre Apress.Printemps.Persistance.avec.Hiberner.Oct.2010

Le but de l'injection de dépendance est de dissocier le travail de résoudre les composants logiciels externes de votre entreprise d'application logique.Sans injection de dépendance, les détails de comment un composant accès les services requis peuvent être embrouillés avec les code. Cela augmente non seulement le potentiel erreurs, ajoute du code gonfle, et amplifie les complexités d'entretien; il Couple les composants ensemble plus étroitement, ce qui rend difficile la modification des dépendances refactoring ou de test.

4
répondu BERGUIGA Mohamed Amine 2015-08-28 10:00:30

injection de dépendance (DI) est un de Design Patterns, qui utilise la caractéristique de base de OOP - la relation dans un objet avec un autre objet. Alors que l'héritage hérite d'un objet pour faire plus complexe et spécifique un autre objet, la relation ou l'association crée simplement un pointeur vers un autre objet à partir d'un objet en utilisant un attribut. La puissance de DI est en combinaison avec d'autres caractéristiques de OOP comme le sont les interfaces et le code de dissimulation. Supposons que nous ayons un client (abonné) dans le bibliothèque, qui peut emprunter un seul livre pour la 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 sortes de livres; un de type est la 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);
}
}

maintenant l'abonné peut avoir l'association 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) {

}

}

toutes les trois classes peuvent être cachées pour sa 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 y a beaucoup différentes façons d'utiliser l'injection de dépendance. Il est possible de le combiner avec Singleton, etc., mais encore en basic il est seulement association réalisée en créant l'attribut de type d'objet à l'intérieur d'un autre objet. L'utilité est seulement et uniquement en fonction, de ce code, nous devrions écrire encore et encore est toujours préparé et fait pour nous avant. C'est pourquoi DI si étroitement lié avec L'Inversion de contrôle (coi) qui signifie, que notre programme passe le contrôle d'un autre module courant, ce qui ne les injections de haricots à notre code. (Chaque objet, qui peut être injecté peut être signé ou est considéré comme un Haricot.) Par exemple au printemps, il est fait par la création et l'initialisation ApplicationContext conteneur, qui fait ce travail pour nous. Nous créons simplement dans notre code le contexte et invoquons l'initialisation des haricots. En ce moment, l'injection a été faite automatiquement.

4
répondu hariprasad 2017-05-19 11:28:03

en mots simples l'injection de dépendance (DI) est le moyen de supprimer les dépendances ou le couplage serré entre différents objets. L'Injection de dépendances donne un comportement cohésif à chaque objet.

DI est la mise en œuvre du directeur du CIO de printemps qui dit "ne nous appelez pas nous vous appellerons". Utiliser le programmeur d'injection de dépendances n'a pas besoin de créer d'objet en utilisant le nouveau mot-clé.

objets sont une fois chargés dans un conteneur à ressort et puis nous réutilisez-les chaque fois que nous en avons besoin en récupérant ces objets à partir du conteneur de printemps en utilisant la méthode getBean(chaîne de Beanname).

3
répondu Waqas Ahmed 2014-05-08 19:57:52

l'injection de dépendance est au cœur du concept lié au cadre de ressort.Tout en créant le cadre de n'importe quel ressort de projet peut jouer un rôle vital,et ici l'injection de dépendance viennent en pichet.

en fait,supposons qu'en java vous avez créé deux classes différentes comme classe A et Classe B, et quelle que soit la fonction disponible dans la Classe B que vous voulez utiliser dans la classe a, donc à ce moment-là l'injection de dépendance peut être utilisée. où vous pouvez créer un objet d'une classe dans autre, de la même manière vous pouvez injecter une classe entière dans une autre classe pour la rendre accessible. de cette façon, la dépendance peut être surmontée.

L'INJECTION DE DÉPENDANCE CONSISTE SIMPLEMENT À COLLER DEUX CLASSES ET EN MÊME TEMPS À LES SÉPARER.

3
répondu mohit sarsar 2014-05-28 09:08:59

l'Injection de Dépendance (DI) est la partie de l'Inversion de Dépendance Principe (DIP) de la pratique, qui est aussi appelé Inversion de Contrôle (IoC). Fondamentalement, vous devez faire DIP parce que vous voulez rendre votre code plus modulaire et unité testable, au lieu d'un seul système monolithique. Vous commencez donc à identifier les parties du code qui peuvent être séparées de la classe et abstraites. Maintenant, la mise en œuvre de l'abstraction doit être injectée à l'extérieur de la classe. Normalement, cela peut être fait via le constructeur. Ainsi, vous créez un constructeur qui accepte l'abstraction comme paramètre, et cela s'appelle l'injection de dépendances (via le constructeur). Pour plus d'explications sur le conteneur DIP, DI, et IoC vous pouvez lire ici

3
répondu kusnaditjung tjung 2016-06-03 23:41:46

Dependency Injection est un type de mise en œuvre du" Inversion de contrôle " principe sur lequel est basée la construction de cadres.

Cadres , comme indiqué dans "Modèle de Conception" de GoF sont des classes qui implémentent les principaux flux de contrôle logique de sensibilisation au développeur de faire que, de cette façon, les Cadres de réaliser l'inversion de contrôle principe.

une façon de mettre en œuvre en tant que technique, et non en tant que hiérarchie de classe, ce principe du CIO n'est qu'une Injection de dépendance.

DI consiste principalement à déléguer la mise en correspondance des instances de classes et de type de référence à ces instances, à une "entité" externe: un objet, une classe statique, un composant, un framework, etc...

classes instances sont les " dépendances ", la liaison externe de l'appel composant avec l'instance de classe par la référence il est le " injection ".

évidemment, vous pouvez mettre en œuvre cette technique de plusieurs façons comme vous le voulez du point de vue OOP, voir par exemple injection constructeur , injection setter , injection interface .

déléguer un tiers pour effectuer la tâche de match a ref à un objet, il est très utile lorsque vous souhaitez séparer complètement un composant qui a besoin de certains services de la même mise en œuvre des services.

ainsi, lors de la conception de composants, vous pouvez vous concentrer exclusivement sur leur architecture et leur logique spécifique, en vous fiant aux interfaces pour collaborer avec d'autres objets sans vous soucier de tout type de mise en œuvre des changements d'objets/services utilisés, même si le même objet que vous utilisez sera totalement remplacé (respect évident de l'interface).

1
répondu Ciro Corvino 2016-11-17 22:57:25

je proposerais une définition légèrement différente, courte et précise de ce Qu'est L'Injection de dépendance, en se concentrant sur le but principal, et non sur les moyens techniques (suivant le long de ici ):

L'Injection de dépendance est le processus de création de la statique, apatride graphique des objets de service, où chaque service est réglée par ses dépendance.

Les objets que nous créons dans nos applications (indépendamment du fait que nous utilisions Java, C# ou d'autres langages orientés objet) appartiennent généralement à l'une des deux catégories suivantes: les "objets de service" (modules) apatrides, statiques et globaux, et les "objets de données"stateful, dynamiques et locaux.

le graphique du module - le graphique des objets de service - est typiquement créé au démarrage de l'application. Cela peut être fait en utilisant un conteneur, comme un ressort, mais peut aussi être fait manuellement, en passant des paramètres aux constructeurs d'objets. Les deux méthodes les ont leurs avantages et inconvénients, mais un cadre n'est certainement pas nécessaire D'utiliser DI dans votre application.

une condition est que les services doivent être paramétrés par leurs dépendances. Ce que cela signifie exactement dépend du langage et de l'approche adoptée dans un système donné. Habituellement, 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 cachées (lors de l'invocation d'une méthode de service) aux utilisateurs de la service.

quand utiliser? Je dirais que chaque fois que l'application est assez grande pour encapsuler la logique dans des modules séparés, avec un graphe de dépendance entre les modules donne un gain de lisibilité et d'explorabilité du code.

1
répondu adamw 2018-09-21 09:42:34