Quelle est la différence entre L'Injection de dépendance et les modèles de localisation de Service?

les deux modèles semblent être une mise en œuvre du principe de l'inversion du contrôle. C'est, qu'un objet ne doit pas savoir construire ses dépendances.

Dependency Injection (DI) semble utiliser un constructeur ou un setter pour "injecter" ses dépendances.

exemple d'utilisation de L'Injection par le constructeur:

//Foo Needs an IBar
public class Foo
{
  private IBar bar;

  public Foo(IBar bar)
  {
    this.bar = bar;
  }

  //...
}

Localisateur de Service semble utiliser un "conteneur", qui dépendences et donne foo c'est la barre.

exemple d'utilisation d'un Localisateur de Service:

//Foo Needs an IBar
public class Foo
{
  private IBar bar;

  public Foo()
  {
    this.bar = Container.Get<IBar>();
  }

  //...
}

parce que nos dépendances ne sont que des objets eux-mêmes, ces dépendances ont des dépendances, qui ont encore plus de dépendances, et ainsi de suite. Ainsi, l'Inversion du conteneur de contrôle (ou conteneur DI) est née. Exemples: Château de Windsor, Ninject, la Structure de la Carte, Printemps, etc.)

mais un Conteneur ressemble exactement comme un Localisateur de Service. Est il appelle un Conteneur d'injection de dépendances un mauvais nom? Un conteneur IOC / DI n'est-il qu'un autre type De Localisateur de Service? Est la nuance dans le fait que nous utilisons des conteneurs DI la plupart du temps quand nous avons de nombreuses dépendances?

237
demandé sur Bogdan Verbenets 2009-10-13 05:15:19

13 réponses

la différence peut sembler légère, mais même avec le ServiceLocator, la classe reste responsable de la création de ses dépendances. Il utilise juste le localisateur de service pour le faire. Avec DI, la classe est donnée ses dépendances. Il ne sait ni ne se soucie d'où ils viennent. Un résultat important de ceci est que L'exemple DI est beaucoup plus facile à tester unité-parce que vous pouvez passer des implémentations mock de ses objets dépendants. Vous pouvez combiner les deux et injecter le service localisateur (ou une usine), si vous vouliez.

143
répondu tvanfosson 2009-10-13 01:24:55

lorsque vous utilisez un localisateur de service, chaque classe sera dépendante de votre Localisateur de service. Ce n'est pas le cas pour l'injection de dépendances. L'injecteur de dépendances ne sera généralement appelé qu'une seule fois au démarrage pour injecter des dépendances dans une classe principale. Les classes dont dépend cette classe principale se verront injecter récursivement leurs dépendances, jusqu'à ce que vous ayez un graphique objet complet.

une bonne comparaison: http://martinfowler.com/articles/injection.html

si votre injecteur de dépendance ressemble à un localisateur de service, où les classes appellent directement l'injecteur, ce n'est probablement pas un injecteur de dépendance, mais plutôt un localisateur de service.

73
répondu Joel 2009-10-13 01:28:13

localisateurs de Service masquer les dépendances - vous ne pouvez pas dire en regardant un objet si elle frappe une base de données ou non (par exemple) quand il obtient des connexions à partir d'un localisateur. Avec l'injection de dépendances (au moins l'injection du constructeur), les dépendances sont explicites.

de plus, les localisateurs de service cassent l'encapsulation parce qu'ils fournissent un point global d'accès aux dépendances d'autres objets. Avec Localisateur de service, comme avec tout singleton :

il devient difficile de préciser le pré et le post conditions de l'objet client l'interface, parce que le fonctionnement de ses la mise en œuvre peut être touché à partir de l'extérieur.

avec l'injection de dépendances, une fois que les dépendances d'un objet sont spécifiées, elles sont sous le contrôle de l'objet lui-même.

39
répondu Jeff Sternal 2009-12-17 16:53:18

Martin Fowler déclare :

avec Localisateur de service la classe d'application le demande explicitement par un message au localisateur. Avec injection il n'y a pas de demande explicite, le service apparaît dans la classe d'application – d'où l'inversion de contrôle.

en bref: Localisateur de Service et Injection de dépendances ne sont que des implémentations du principe D'Inversion de dépendance.

le principe important est de "dépendre d'Abstractions, et non de concrétions". Cela rendra votre conception de logiciel "vaguement couplé"," extensible","flexible".

vous pouvez utiliser celui qui répond le mieux à vos besoins. Pour une grande application, ayant une énorme base de codes, vous feriez mieux d'utiliser un Localisateur de Service, parce que L'Injection de dépendances nécessiterait plus de modifications à votre base de codes.

vous pouvez vérifier ce post: Inversion de dépendance: Localisateur de Service ou Injection de dépendance

aussi le classique: Inversion des conteneurs de commande et le schéma D'Injection de dépendance par Martin Fowler

Designing Reusable Classes by Ralph E. Johnson & Brian Foote

cependant, celui qui m'a ouvert les yeux était: ASP.NET MVC: résoudre ou injecter? C'est le problème ... par Dino Esposito

27
répondu Nathan 2015-08-10 23:26:43

Une classe à l'aide du constructeur DI indique la consommation de code qu'il y a des dépendances à satisfaire. Si la classe utilise le SL en interne pour récupérer de telles dépendances, le code de consommation n'est pas conscient des dépendances. Cela peut sembler mieux à première vue, mais il est en fait utile de connaître toute dépendance explicite. Il est préférable de partir d'une vue architectural. Et quand vous faites des tests, vous devez savoir si une classe a besoin de certaines dépendances, et configurer le SL pour fournir les versions fausses appropriées de ces dépendances. Avec DI, on passe dans les faux. Pas une énorme différence, mais il est là.

DI et SL peuvent travailler ensemble. Il est utile d'avoir un emplacement central pour les dépendances communes (par exemple, paramètres, logger, etc.). Avec une classe utilisant de tels deps, vous pouvez créer un constructeur "réel" qui reçoit les DEP, et un constructeur par défaut (sans paramètre) qui récupère à partir du SL et transmet au constructeur "réel".

Modifier: et, bien sûr, lorsque vous utilisez le SL, vous introduisez un certain couplage à ce composant. Ce qui est ironique, puisque l'idée d'une telle fonctionnalité est d'encourager les abstractions et de réduire le couplage. Les préoccupations peuvent être équilibrées, et cela dépend du nombre d'endroits où vous devez utiliser le SL. Si fait comme suggéré ci-dessus, juste dans le constructeur de classe par défaut.

18
répondu Grant Palin 2009-10-14 17:51:01

je pense que les deux travaillent ensemble.

injection de dépendance signifie que vous poussez dans une classe dépendante/interface vers une classe consommatrice (généralement vers son constructeur). Cela permet de découpler les deux classes via une interface et signifie que la classe de consommation peut fonctionner avec de nombreux types d'implémentations de "dépendance injectée".

le rôle du Localisateur de service est de rassembler votre mise en œuvre. Vous installez un localisateur de service via un cerclage début de votre programme. Bootstrapping est le processus d'association d'un type d'implémentation à un Abstrait/interface particulier. Qui est créé pour vous au moment de l'exécution. (basé sur votre configuration ou bootstrap). Si vous n'aviez pas mis en œuvre l'injection de dépendances, il serait très difficile d'utiliser un localisateur de service ou un conteneur de recherche des causes.

5
répondu NoelAdy 2011-02-19 14:17:22

toutes deux sont des techniques de mise en œuvre du CIO. Il y a aussi d'autres motifs qui mettent en œuvre L'Inversion du contrôle:

  • dessin d'usine
  • Localisateur de service
  • injection de dépendance (injection du constructeur, injection du paramètre (si non nécessaire), injection du setter d'injection de l'interface) ...

Localisateur de Service et DI semble plus similaire, tous les deux utilisent un conteneur définir les dépendances, qui établit une correspondance entre l'abstraction et la mise en œuvre concrète.

la principale différence est la façon dont les dépendances sont localisées, dans le service Location client code demande les dépendances , dans DI nous utilisons le conteneur pour créer tous les objets et il injecte la dépendance comme paramètres de constructeur (ou propriétés).

5
répondu Nininea 2015-02-22 21:03:33

dans mon dernier projet, j'utilise les deux. J'utilise l'injection de dépendance pour tester les unités. J'utilise le Localisateur de service pour masquer l'implémentation et être dépendant de mon conteneur CIO. et oui! Une fois que vous utilisez L'un des conteneurs du CIO (Unity, Ninject, Windsor Castle), vous en dépendez. Et une fois qu'il est obsolète ou pour une raison quelconque si vous voulez l'échanger, vous devrez/devrez peut - être changer votre implémentation-au moins la composition root. Mais le Localisateur de service fait abstraction de cette phase.

How vous ne dépendriez pas de votre conteneur CIO? Soit vous aurez besoin de l'envelopper vous-même (ce qui est une mauvaise idée) ou vous utilisez le Localisateur de Service configurer votre conteneur CIO. Vous allez donc dire à Localisateur de service d'obtenir l'interface dont vous avez besoin, et il appellera conteneur IoC configuré pour récupérer cette interface.

dans mon cas, j'utilise ServiceLocator qui est un composant de cadre. Et utiliser Unité pour le conteneur IoC. Si à l'avenir j'ai besoin pour passer mon conteneur IoC à Ninject tout ce que je dois faire est de configurer mon Localisateur de Service pour utiliser Ninject au lieu de Unity. Migration facile.

voici un grand article explique ce scénario; http://www.johandekoning.nl/index.php/2013/03/03/dont-wrap-your-ioc-container /

5
répondu Teoman shipahi 2015-08-03 19:33:13

une raison d'ajouter, inspiré par une mise à jour de la documentation que nous avons écrite pour le projet MEF la semaine dernière (j'aide à construire MEF).

une Fois qu'une application est composée de potentiellement des milliers de composants, il peut être difficile de déterminer si un composant particulier peut être instancié correctement. Par "instancié correctement", je veux dire que, dans cet exemple basé sur le Foo composant, une instance de IBar et sera disponible, et que le composant fournissant will:

  • avoir ses dépendances nécessaires,
  • ne pas participer à des cycles de dépendance invalides, et
  • dans le cas de MEF, être fourni avec un seul cas.

dans le deuxième exemple que vous avez donné, où le constructeur va au conteneur IoC pour récupérer ses dépendances, la seule façon que vous pouvez tester qu'une instance de Foo sera capable d'être instanciée correctement avec la configuration de l'exécution de votre application est à construire .

cela a toutes sortes d'effets secondaires gênants au moment de l'essai, parce que le code qui fonctionnera à l'exécution ne fonctionnera pas nécessairement sous un harnais d'essai. Les moqueurs ne le feront pas, parce que la vraie configuration est la chose que nous devons tester, pas une configuration de test-time.

la racine de ce problème est la différence déjà appelé par @Jon: injecter des dépendances à travers le constructeur est déclaratif, tandis que la seconde version utilise le modèle de localisateur de Service impératif.

un conteneur IoC, lorsqu'il est utilisé avec soin, peut analyser statiquement la configuration runtime de votre application sans créer aucune instance des composants impliqués. De nombreux conteneurs populaires fournissent une certaine variation de cela; Microsoft.Composition , qui est la version de MEF targeting. net 4.5 applications web et Metro style, fournit un exemple CompositionAssert dans la documentation wiki. En l'utilisant, vous pouvez écrire le code comme:

 // Whatever you use at runtime to configure the container
var container = CreateContainer();

CompositionAssert.CanExportSingle<Foo>(container);

(voir cet exemple ).

en vérifiant la Composition Roots de votre application au moment du test, vous pouvez potentiellement attraper certaines erreurs qui pourraient autrement glisser à travers les tests plus tard dans le processus.

l'Espérance, c'est intéressant outre ce large ensemble de réponses sur le sujet!

4
répondu Nicholas Blumhardt 2016-12-10 16:09:16

Note: Je ne réponds pas exactement à la question. Mais je pense que cela peut être utile pour les nouveaux apprenants du modèle D'Injection de dépendance qui sont confondus à ce sujet avec le Localisateur de Service (anti-)modèle qui se trouvent à trébucher sur cette page.

je sais la différence entre le Localisateur de Service (il semble être considéré comme un anti-modèle maintenant) et les modèles D'Injection de dépendance et peut comprendre des exemples concrets chaque modèle, pourtant je était confus par les exemples montrant un localisateur de service à l'intérieur du constructeur (supposons que nous faisons l'injection du constructeur).

"Localisateur de Service" est souvent utilisé à la fois comme nom d'un motif et comme nom pour désigner l'objet (supposons aussi) utilisé dans ce motif pour obtenir des objets sans utiliser le nouvel opérateur. Maintenant, ce même type d'objet peut aussi être utilisé à la composition root pour effectuer l'injection de dépendances, et c'est là que la confusion vient dans.

le fait est que vous pouvez utiliser un objet de localisation de service à l'intérieur d'un constructeur DI, mais vous n'utilisez pas le"modèle de localisation de Service". Il est moins déroutant si on le réfère plutôt comme un objet conteneur du CIO, car vous avez peut-être deviné qu'ils font essentiellement la même chose (corrigez-moi si je me trompe).

Qu'il soit désigné comme un localisateur de service (ou juste Localisateur), ou comme un conteneur IoC (ou juste conteneur) ne fait pas différence comme vous avez deviner car ils se réfèrent probablement à la même abstraction (ne me corrigez si je me trompe). C'est juste que le fait de l'appeler un localisateur de service suggère que l'on utilise l'anti-pattern du Localisateur de Service avec le pattern D'Injection de dépendances.

à mon humble avis, en le nommant un "localisateur" au lieu de "localisation" ou "localisation", peut également provoquer une pense parfois que le service locator dans un article parlant du Service Localisateur de conteneur, et de ne pas le Modèle de localisateur de Service (anti -), surtout lorsqu'il y a un modèle connexe appelé Injection de dépendance et non Injecteur de dépendance.

3
répondu blizpasta 2012-01-10 08:07:53

dans ce cas simplifié, il n'y a pas de différence et ils peuvent être utilisés de manière interchangeable. Cependant, les problèmes du monde réel ne sont pas aussi simples. Supposons que la classe de barre elle-même ait une autre dépendance nommée D. Dans ce cas, votre Localisateur de service ne serait pas capable de résoudre cette dépendance et vous auriez à l'instancier dans la classe D; parce que c'est la responsabilité de vos classes d'instancier leurs dépendances. Il serait même pire si la classe D elle-même avait d'autres les dépendances et dans des situations réelles, cela devient généralement encore plus compliqué que cela. Dans de tels scénarios, DI est une meilleure solution que ServiceLocator.

3
répondu Daniel 2016-05-31 12:28:05

Quelle est la différence (le cas échéant) entre L'Injection de dépendance et le Localisateur de Service? Les deux modèles sont bons pour mettre en œuvre le principe de L'Inversion de dépendance. Le modèle de localisateur de Service est plus facile à utiliser dans une base de codes existante car il rend la conception globale plus souple sans forcer des changements à l'interface publique. Pour cette même raison, le code qui est basé sur le modèle de localisateur de Service est moins lisible que le code équivalent qui est basé sur L'Injection de dépendances.

le schéma D'Injection de dépendances indique clairement depuis la signature quelles dépendances une classe (ou une méthode) va avoir. Pour cette raison, le code résultant est plus propre et plus lisible.

1
répondu Yogesh Joshi 2017-01-23 11:30:59

Pour le dossier

//Foo Needs an IBar
public class Foo
{
  private IBar bar;

  public Foo(IBar bar)
  {
    this.bar = bar;
  }

  //...
}

sauf si vous avez vraiment besoin d'une interface (l'interface est utilisée par Plus d'une classe), vous ne devez pas L'utiliser . Dans ce cas, IBar permet d'utiliser n'importe quelle classe de service, qui le met en œuvre. Cependant, habituellement, cette Interface sera utilisée par une seule classe.

Pourquoi c'est une mauvaise idée d'utiliser une interface?. Parce que c'est vraiment difficile à déboguer.

par exemple, disons que l'instance "barre" a échoué, question: quelle classe a échoué?. quel code dois-je fixer? un point de vue simple, il mène à une Interface, et c'est ici où ma route se termine.

à la place, si le code utilise une dépendance dure alors il est facile de déboguer une erreur.

//Foo Needs an IBar
public class Foo
{
  private BarService bar;

  public Foo(IBar bar)
  {
    this.bar = bar;
  }

  //...
}

si " bar " échoue, alors je devrais vérifier et d'abord la classe BarService.

0
répondu magallanes 2018-09-30 00:47:21