Was ist der Unterschied zwischen den Mustern Dependency Injection und Service Locator?


304

Beide Muster scheinen eine Umsetzung des Prinzips der Umkehrung der Kontrolle zu sein. Das heißt, dass ein Objekt nicht wissen sollte, wie es seine Abhängigkeiten konstruiert.

Dependency Injection (DI) scheint einen Konstruktor oder Setter zu verwenden, um seine Abhängigkeiten zu "injizieren".

Beispiel für die Verwendung der Konstruktorinjektion:

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

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

  //...
}

Service Locator scheint einen "Container" zu verwenden, der seine Abhängigkeiten verkabelt und foo seine Leiste gibt.

Beispiel für die Verwendung eines Service Locator:

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

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

  //...
}

Da unsere Abhängigkeiten nur Objekte selbst sind, haben diese Abhängigkeiten Abhängigkeiten, die noch mehr Abhängigkeiten aufweisen, und so weiter und so fort. So wurde die Inversion des Kontrollcontainers (oder DI-Containers) geboren. Beispiele: Castle Windsor, Ninject, Strukturkarte, Frühling usw.)

Ein IOC / DI-Container sieht jedoch genauso aus wie ein Service Locator. Ist es ein schlechter Name, wenn man es DI-Container nennt? Ist ein IOC / DI-Container nur eine andere Art von Service Locator? Liegt die Nuance in der Tatsache, dass wir DI-Container meistens verwenden, wenn wir viele Abhängigkeiten haben?


13
Umkehrung der Kontrolle bedeutet, dass "ein Objekt nicht wissen sollte, wie es seine Abhängigkeiten konstruiert"?!? Das ist neu für mich. Nein, wirklich, das ist nicht das, was "Umkehrung der Kontrolle" bedeutet. Siehe martinfowler.com/bliki/InversionOfControl.html Dieser Artikel enthält sogar Referenzen zur Etymologie des Begriffs aus den 1980er Jahren.
Rogério


1
Mark Seemann argumentiert Service Locator als Anti-Pattern ( blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern ). Außerdem fand ich das Diagramm (hier zu finden, stackoverflow.com/a/9503612/1977871 ) hilfreich, um die DI- und SL-Situation zu verstehen. Hoffe das hilft.
VivekDev

Antworten:


181

Der Unterschied mag geringfügig erscheinen, aber selbst mit dem ServiceLocator ist die Klasse weiterhin für das Erstellen ihrer Abhängigkeiten verantwortlich. Es wird nur der Service Locator verwendet, um dies zu tun. Mit DI erhält die Klasse ihre Abhängigkeiten. Es weiß weder, noch kümmert es, woher sie kommen. Ein wichtiges Ergebnis davon ist, dass das DI-Beispiel viel einfacher zu testen ist, da Sie es Scheinimplementierungen seiner abhängigen Objekte übergeben können. Sie können beides kombinieren - und den Service Locator (oder eine Fabrik) einspritzen, wenn Sie möchten.


20
Darüber hinaus können Sie beim Erstellen einer Klasse beide verwenden. Der Standardkonstruktor kann die SL verwenden, um die Abhängigkeiten abzurufen und an den "echten" Konstruktor zu übergeben, der diese Abhängigkeiten empfängt. Sie bekommen das Beste aus beiden Welten.
Grant Palin

6
Nein, der ServiceLocator ist dafür verantwortlich, die korrekte Implementierung für eine bestimmte Abhängigkeit (Plugin) zu instanziieren. Im Fall von DI ist der DI "Container" derjenige, der dafür verantwortlich ist.
Rogério

5
@ Rogerio ja, aber die Klasse muss noch etwas über den Service Locator wissen ... das sind zwei Abhängigkeiten. Außerdem habe ich häufig gesehen, dass Service Locator an den DI-Container delegiert wurde, um nach transienten Objekten zu suchen, die Serviceunterstützung benötigen.
Adam Gent

2
@Adam Ich habe nicht gesagt, dass der Service Locator an einen DI-Container delegieren würde. Dies sind zwei sich gegenseitig ausschließende Muster, wie im "offiziellen" Artikel beschrieben . Für mich hat Service Locator in der Praxis einen großen Vorteil gegenüber DI: Die Verwendung eines DI-Containers führt zu Missbrauch (den ich wiederholt gesehen habe), während die Verwendung eines Service Locator dies nicht tut.
Rogério

3
"Ein wichtiges Ergebnis davon ist, dass das DI-Beispiel viel einfacher zu testen ist - weil Sie es Scheinimplementierungen seiner abhängigen Objekte übergeben können." Nicht wahr. In Ihren Komponententests kann ein Aufruf einer Registerfunktion im Service Locator-Container verwendet werden, um der Registrierung auf einfache Weise Mocks hinzuzufügen.
Drumbeg

93

Wenn Sie einen Service Locator verwenden, ist jede Klasse von Ihrem Service Locator abhängig. Dies ist bei der Abhängigkeitsinjektion nicht der Fall. Der Abhängigkeitsinjektor wird normalerweise beim Start nur einmal aufgerufen, um Abhängigkeiten in eine Hauptklasse zu injizieren. Bei den Klassen, von denen diese Hauptklasse abhängt, werden ihre Abhängigkeiten rekursiv eingefügt, bis Sie ein vollständiges Objektdiagramm haben.

Ein guter Vergleich: http://martinfowler.com/articles/injection.html

Wenn Ihr Abhängigkeitsinjektor wie ein Service Locator aussieht, bei dem die Klassen den Injector direkt aufrufen, handelt es sich wahrscheinlich nicht um einen Abhängigkeitsinjektor, sondern um einen Service Locator.


17
Aber wie gehen Sie mit dem Fall um, in dem Sie zur Laufzeit Objekte erstellen müssen? Wenn Sie sie manuell mit "neu" erstellen, können Sie DI nicht verwenden. Wenn Sie das DI-Framework um Hilfe bitten, brechen Sie das Muster. Welche Optionen bleiben also übrig?
Boris

9
@ Boris Ich hatte das gleiche Problem und beschloss, klassenspezifische Fabriken zu injizieren. Nicht hübsch, aber erledigt. Würde gerne eine schönere Lösung sehen.
Charlie Rudenstål

Direkter Link zum Vergleich: martinfowler.com/articles/…
Teoman shipahi

2
@Boris Wenn ich neue Objekte im laufenden Betrieb erstellen müsste, würde ich eine Abstract Factory für diese Objekte einfügen. Dies ähnelt dem Injizieren eines Service Locators in diesem Fall, bietet jedoch eine konkrete, einheitliche Schnittstelle zur Kompilierungszeit zum Erstellen der relevanten Objekte und macht die Abhängigkeiten explizit.
LivePastTheEnd

51

Service Locators verbergen Abhängigkeiten - Sie können anhand eines Objekts nicht erkennen, ob es auf eine Datenbank trifft oder nicht (zum Beispiel), wenn es Verbindungen von einem Locator erhält. Bei der Abhängigkeitsinjektion (zumindest der Konstruktorinjektion) sind die Abhängigkeiten explizit.

Darüber hinaus unterbrechen Service Locators die Kapselung, da sie einen globalen Zugriffspunkt auf Abhängigkeiten anderer Objekte bieten. Mit Service Locator wie mit jedem Singleton :

Es wird schwierig, die Vor- und Nachbedingungen für die Schnittstelle des Clientobjekts anzugeben, da die Funktionsweise seiner Implementierung von außen beeinflusst werden kann.

Bei der Abhängigkeitsinjektion haben die Abhängigkeiten eines Objekts, sobald sie angegeben wurden, die Kontrolle über das Objekt selbst.



2
Ich liebe den alten Steve Yegge und der Titel dieses Artikels ist großartig, aber ich denke, der Artikel, den ich zitiert habe, und Miško Heverys "Singletons sind pathologische Lügner" ( misko.hevery.com/2008/08/17/singletons-are-pathological- Lügner ) machen ein besseres Argument gegen die besondere Teufelei des Service Locator.
Jeff Sternal

Diese Antwort ist die richtigste, da sie einen Service Locator am besten definiert: "Eine Klasse, die ihre Abhängigkeiten verbirgt." Beachten Sie, dass das interne Erstellen einer Abhängigkeit zwar oft keine gute Sache ist, eine Klasse jedoch nicht zu einem Service Locator macht. Die Abhängigkeit von einem Container ist ebenfalls ein Problem, aber nicht "das" Problem, das einen Service Locator am klarsten definiert.
Sam

1
With dependency injection (at least constructor injection) the dependencies are explicit.. Bitte erkläre.
FindOutIslamNow

Wie oben kann ich nicht sehen, wie SL Abhängigkeiten weniger explizit macht als DI ...
Michał Powłoka

38

Martin Fowler erklärt :

Bei Service Locator fordert die Anwendungsklasse dies explizit durch eine Nachricht an den Locator an. Bei der Injektion erfolgt keine explizite Anforderung, der Dienst wird in der Anwendungsklasse angezeigt - daher die Umkehrung der Steuerung.

Kurz gesagt: Service Locator und Dependency Injection sind nur Implementierungen des Dependency Inversion Principle.

Das wichtige Prinzip lautet „Abhängig von Abstraktionen, nicht von Konkretionen“. Dadurch wird Ihr Software-Design „lose gekoppelt“, „erweiterbar“ und „flexibel“.

Sie können diejenige verwenden, die Ihren Anforderungen am besten entspricht. Für eine große Anwendung mit einer großen Codebasis sollten Sie einen Service Locator verwenden, da für die Abhängigkeitsinjektion mehr Änderungen an Ihrer Codebasis erforderlich sind.

Sie können diesen Beitrag überprüfen: Abhängigkeitsinversion: Service Locator oder Abhängigkeitsinjektion

Auch der Klassiker: Inversion von Kontrollcontainern und das Abhängigkeitsinjektionsmuster von Martin Fowler

Entwerfen wiederverwendbarer Klassen von Ralph E. Johnson & Brian Foote

Das, was mir die Augen öffnete, war jedoch: ASP.NET MVC: Auflösen oder Injizieren? Das ist das Problem… von Dino Esposito


Fantastische Zusammenfassung: "Service Locator und Dependency Injection sind nur Implementierungen des Dependency Inversion Principle."
Hans

Und er stellt außerdem fest: Der Hauptunterschied besteht darin, dass bei einem Service Locator jeder Benutzer eines Service eine Abhängigkeit vom Locator hat. Der Locator kann Abhängigkeiten zu anderen Implementierungen ausblenden, Sie müssen jedoch den Locator sehen. Die Entscheidung zwischen Locator und Injektor hängt also davon ab, ob diese Abhängigkeit ein Problem darstellt.
Programme

1
ServiceLocator und DI haben nichts mit dem "Dependency Inversion Principle" (DIP) zu tun. DIP ist eine Möglichkeit, eine Komponente auf hoher Ebene wiederverwendbarer zu machen, indem eine Abhängigkeit zur Kompilierungszeit von einer Komponente auf niedriger Ebene durch eine Abhängigkeit von einem abstrakten Typ ersetzt wird, der zusammen mit der Komponente auf hoher Ebene definiert wird, die von der Komponente auf niedriger Ebene implementiert wird. Level-Komponente; Auf diese Weise wird die Abhängigkeit zur Kompilierungszeit invertiert, da jetzt die Abhängigkeit auf niedriger Ebene von der Abhängigkeit auf hoher Ebene abhängt. Beachten Sie auch, dass Martin Fowlers Artikel erklärt, dass DI und IoC dies nicht sind dasselbe sind.
Rogério

23

Eine Klasse, die den Konstruktor DI verwendet, zeigt dem konsumierenden Code an, dass Abhängigkeiten erfüllt werden müssen. Wenn die Klasse den SL intern zum Abrufen solcher Abhängigkeiten verwendet, kennt der konsumierende Code die Abhängigkeiten nicht. Dies mag auf den ersten Blick besser erscheinen, aber es ist tatsächlich hilfreich, explizite Abhängigkeiten zu kennen. Aus architektonischer Sicht ist es besser. Wenn Sie Tests durchführen, müssen Sie wissen, ob eine Klasse bestimmte Abhängigkeiten benötigt, und den SL so konfigurieren, dass geeignete gefälschte Versionen dieser Abhängigkeiten bereitgestellt werden. Mit DI geben Sie einfach die Fälschungen ein. Kein großer Unterschied, aber es ist da.

DI und SL können jedoch zusammenarbeiten. Es ist nützlich, einen zentralen Speicherort für allgemeine Abhängigkeiten zu haben (z. B. Einstellungen, Logger usw.). Wenn eine Klasse solche deps verwendet, können Sie einen "echten" Konstruktor erstellen, der die deps empfängt, und einen Standardkonstruktor (ohne Parameter), der vom SL abgerufen und an den "echten" Konstruktor weitergeleitet wird.

BEARBEITEN: und wenn Sie den SL verwenden, führen Sie natürlich eine gewisse Kopplung an diese Komponente ein. Das ist ironisch, da die Idee einer solchen Funktionalität darin besteht, Abstraktionen zu fördern und die Kopplung zu verringern. Die Bedenken können ausgeglichen werden und es hängt davon ab, an wie vielen Stellen Sie den SL verwenden müssten. Wenn dies wie oben vorgeschlagen erfolgt, nur im Standardklassenkonstruktor.


Interessant! Ich verwende sowohl DI als auch SL, aber nicht mit zwei Konstruktoren. Drei oder vier langweiligste, häufig benötigte Abhängigkeiten (Einstellungen usw.) werden vom SL im laufenden Betrieb abgerufen. Alles andere wird vom Konstruktor injiziert. Es ist ein bisschen hässlich, aber pragmatisch.
Maaartinus

10

Beide sind Implementierungstechniken von IoC. Es gibt auch andere Muster, die Inversion of Control implementieren:

  • Fabrikmuster
  • Service Locator
  • DI (IoC) Container
  • Abhängigkeitsinjektion (Konstruktorinjektion, Parameterinjektion (falls nicht erforderlich), Setterinjektion der Schnittstelleninjektion) ...

Service Locator und DI Container scheinen sich ähnlicher zu sein. Beide verwenden einen Container, um Abhängigkeiten zu definieren, der die Abstraktion der konkreten Implementierung zuordnet.

Der Hauptunterschied besteht darin, wie sich die Abhängigkeiten befinden. In Service Locator fordert der Clientcode die Abhängigkeiten an. In DI Container verwenden wir einen Container, um alle Objekte zu erstellen, und er fügt Abhängigkeiten als Konstruktorparameter (oder Eigenschaften) ein.


7

In meinem letzten Projekt benutze ich beide. Ich verwende die Abhängigkeitsinjektion für die Einheitentestbarkeit. Ich verwende den Service Locator, um die Implementierung zu verbergen und von meinem IoC-Container abhängig zu sein. und ja! Sobald Sie einen der IoC-Container (Unity, Ninject, Windsor Castle) verwenden, sind Sie darauf angewiesen. Und sobald es veraltet ist oder aus irgendeinem Grund, wenn Sie es austauschen möchten, müssen / müssen Sie möglicherweise Ihre Implementierung ändern - zumindest den Kompositionsstamm. Aber Service Locator abstrahiert diese Phase.

Wie würden Sie sich nicht auf Ihren IoC-Container verlassen? Entweder müssen Sie es selbst verpacken (was eine schlechte Idee ist) oder Sie verwenden Service Locator, um Ihren IoC-Container zu konfigurieren. Sie teilen dem Service Locator mit, welche Schnittstelle Sie benötigen, und rufen den IoC-Container auf, der zum Abrufen dieser Schnittstelle konfiguriert ist.

In meinem Fall verwende ich ServiceLocator , eine Framework-Komponente. Und verwenden Sie Unity für IoC-Container. Wenn ich in Zukunft meinen IoC-Container gegen Ninject austauschen muss, muss ich lediglich meinen Service Locator so konfigurieren, dass Ninject anstelle von Unity verwendet wird. Einfache Migration.

Hier ist ein großartiger Artikel, der dieses Szenario erklärt. http://www.johandekoning.nl/index.php/2013/03/03/dont-wrap-your-ioc-container/


Der Johandekoning-Artikellink ist defekt.
JakeJ

6

Ich denke, die beiden arbeiten zusammen.

Abhängigkeitsinjektion bedeutet, dass Sie eine abhängige Klasse / Schnittstelle an eine konsumierende Klasse (normalerweise an deren Konstruktor) senden. Dies entkoppelt die beiden Klassen über eine Schnittstelle und bedeutet, dass die konsumierende Klasse mit vielen Arten von Implementierungen mit "injizierter Abhängigkeit" arbeiten kann.

Die Rolle des Service Locators besteht darin, Ihre Implementierung zusammenzuführen. Sie richten zu Beginn Ihres Programms einen Service Locator über ein Boot Strapping ein. Beim Bootstrapping wird ein Implementierungstyp einer bestimmten Zusammenfassung / Schnittstelle zugeordnet. Was zur Laufzeit für Sie erstellt wird. (basierend auf Ihrer Konfiguration oder Ihrem Bootstrap). Wenn Sie die Abhängigkeitsinjektion nicht implementiert hätten, wäre es sehr schwierig, einen Service Locator oder einen IOC-Container zu verwenden.


6

Ein Grund zum Hinzufügen, inspiriert von einem Dokumentationsupdate, das wir letzte Woche für das MEF-Projekt geschrieben haben (ich helfe beim Aufbau von MEF).

Sobald eine App aus möglicherweise Tausenden von Komponenten besteht, kann es schwierig sein, festzustellen, ob eine bestimmte Komponente korrekt instanziiert werden kann. Mit "korrekt instanziiert" meine ich, dass in diesem Beispiel basierend auf der FooKomponente eine Instanz von IBarund verfügbar sein wird und dass die Komponente, die sie bereitstellt, Folgendes tun wird:

  • haben die erforderlichen Abhängigkeiten,
  • nicht an ungültigen Abhängigkeitszyklen beteiligt sein, und
  • im Fall von MEF mit nur einer Instanz geliefert werden.

Im zweiten Beispiel , das Sie gab, wo der Konstruktor die IoC - Container geht seine Abhängigkeiten abzurufen, dass der einzige Weg , können Sie testen , dass eine Instanz der FooLage sein wird , richtig instanziiert wird mit der tatsächlichen Laufzeitkonfiguration Ihrer App ist eigentlich Konstrukt es .

Dies hat zur Testzeit alle möglichen unangenehmen Nebenwirkungen, da Code, der zur Laufzeit funktioniert, nicht unbedingt unter einem Testkabel funktioniert. Mocks reichen nicht aus, da die eigentliche Konfiguration das ist, was wir testen müssen, nicht irgendein Testzeit-Setup.

Die Wurzel dieses Problems ist der Unterschied, auf den @Jon bereits hingewiesen hat: Das Einfügen von Abhängigkeiten über den Konstruktor ist deklarativ, während die zweite Version das imperative Service Locator-Muster verwendet.

Ein IoC-Container kann bei sorgfältiger Verwendung die Laufzeitkonfiguration Ihrer App statisch analysieren, ohne tatsächlich Instanzen der beteiligten Komponenten zu erstellen. Viele beliebte Behälter bieten eine Variation davon; Microsoft.Composition , die Version von MEF für .NET 4.5-Apps im Web- und Metro-Stil, enthält ein CompositionAssertBeispiel in der Wiki-Dokumentation. Mit ihm können Sie Code schreiben wie:

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

CompositionAssert.CanExportSingle<Foo>(container);

(Siehe dieses Beispiel ).

Durch Überprüfen der Zusammensetzungswurzeln Ihrer Anwendung zum Testzeitpunkt können Sie möglicherweise einige Fehler erkennen, die andernfalls später im Prozess durch den Test rutschen könnten.

Hoffe, dies ist eine interessante Ergänzung zu dieser ansonsten umfassenden Reihe von Antworten zum Thema!


5

Hinweis: Ich beantworte die Frage nicht genau. Ich bin jedoch der Meinung, dass dies für neue Lernende des Abhängigkeitsinjektionsmusters nützlich sein kann, die darüber mit dem Service Locator-Muster (Anti-Muster) verwechselt werden , das zufällig auf diese Seite stößt.

Ich kenne den Unterschied zwischen dem Service Locator (er scheint jetzt als Anti-Pattern angesehen zu werden) und dem Dependency Injection-Muster und kann konkrete Beispiele für jedes Muster verstehen, war jedoch durch Beispiele verwirrt, die einen Service Locator im Konstruktor zeigen (nehmen wir an, wir ' Konstruktorinjektion durchführen).

"Service Locator" wird häufig sowohl als Name eines Musters als auch als Name verwendet, um auf das in diesem Muster verwendete Objekt zu verweisen (auch angenommen), um Objekte zu erhalten, ohne den neuen Operator zu verwenden. Dieser Objekttyp kann jetzt auch im Kompositionsstamm verwendet werden , um eine Abhängigkeitsinjektion durchzuführen, und hier kommt die Verwirrung ins Spiel.

Der Punkt ist, dass Sie möglicherweise ein Service Locator-Objekt in einem DI-Konstruktor verwenden, aber nicht das "Service Locator-Muster". Es ist weniger verwirrend, wenn man es stattdessen als IoC-Containerobjekt bezeichnet, da Sie vielleicht vermutet haben, dass sie im Wesentlichen dasselbe tun (korrigieren Sie mich, wenn ich falsch liege).

Ob es als Service Locator (oder nur als Locator) oder als IoC-Container (oder nur als Container) bezeichnet wird, spielt keine Rolle, wie Sie vermuten, da sie sich wahrscheinlich auf dieselbe Abstraktion beziehen (korrigieren Sie mich, wenn ich falsch liege ). Es ist nur so, dass die Bezeichnung "Service Locator" darauf hindeutet, dass das Service Locator-Antimuster zusammen mit dem Abhängigkeitsinjektionsmuster verwendet wird.

IMHO, wenn man es als "Locator" anstelle von "Location" oder "Locating" bezeichnet, kann man manchmal auch denken, dass sich der Service Locator in einem Artikel auf den Service Locator-Container und nicht auf das Service Locator (Anti-) Muster bezieht , insbesondere wenn es ein verwandtes Muster namens Dependency Injection und nicht Dependency Injector gibt.


4

In diesem stark vereinfachten Fall gibt es keinen Unterschied und sie können austauschbar verwendet werden. Probleme in der realen Welt sind jedoch nicht so einfach. Nehmen Sie einfach an, dass die Bar-Klasse selbst eine andere Abhängigkeit mit dem Namen D hatte. In diesem Fall könnte Ihr Service Locator diese Abhängigkeit nicht auflösen, und Sie müssten sie innerhalb der D-Klasse instanziieren. weil es in der Verantwortung Ihrer Klassen liegt, ihre Abhängigkeiten zu instanziieren. Es würde noch schlimmer werden, wenn die D-Klasse selbst andere Abhängigkeiten hätte und in realen Situationen wird es normalerweise noch komplizierter. In solchen Szenarien ist DI eine bessere Lösung als ServiceLocator.


4
Hmm, ich würde nicht zustimmen: der Service Locator ex. zeigt deutlich, dass dort immer noch eine Abhängigkeit besteht ... der Service Locator. Wenn die barKlasse selbst eine Abhängigkeit hat, dann hat barsie auch einen Service Locator, das ist der springende Punkt bei der Verwendung von DI / IoC.
GFoley83

2

Was ist der Unterschied (falls vorhanden) zwischen Dependency Injection und Service Locator? Beide Muster können das Prinzip der Abhängigkeitsinversion gut implementieren. Das Service Locator-Muster ist in einer vorhandenen Codebasis einfacher zu verwenden, da es das gesamte Design lockert, ohne Änderungen an der öffentlichen Schnittstelle zu erzwingen. Aus demselben Grund ist Code, der auf dem Service Locator-Muster basiert, weniger lesbar als gleichwertiger Code, der auf Dependency Injection basiert.

Das Abhängigkeitsinjektionsmuster macht seit der Signatur deutlich, welche Abhängigkeiten eine Klasse (oder eine Methode) haben wird. Aus diesem Grund ist der resultierende Code sauberer und besser lesbar.


1

Die folgende einfache Konzeption gab mir ein klareres Verständnis des Unterschieds zwischen Service Locator und DI Container:

  • Service Locator wird im Consumer verwendet und ruft Services per ID auf direkte Anfrage des Verbrauchers aus einem Speicher ab

  • DI Container irgendwo außerhalb gelegen und es dauert Dienstleistungen aus einer gewissen Lagerung und drückt sie an den Verbraucher (egal über Konstruktor oder über Verfahren)

Wir können jedoch nur im Zusammenhang mit der konkreten Nutzung durch die Verbraucher über Unterschiede zwischen diesen sprechen. Wenn Service Locator und DI Container in Composition Root verwendet werden, sind sie fast ähnlich.


0

DI-Container ist eine Obermenge von Service Locator. Es kann verwendet werden, um einen Dienst zu lokalisieren , mit der zusätzlichen Fähigkeit, die Injektionen der Abhängigkeit zusammenzusetzen (zu verdrahten) .


-2

Für die Aufzeichnung

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

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

  //...
}

Sofern Sie nicht wirklich eine Schnittstelle benötigen (die Schnittstelle wird von mehr als einer Klasse verwendet), dürfen Sie sie NICHT verwenden . In diesem Fall ermöglicht IBar die Verwendung jeder Serviceklasse, die diese implementiert. Normalerweise wird diese Schnittstelle jedoch von einer einzelnen Klasse verwendet.

Warum ist es eine schlechte Idee, eine Schnittstelle zu verwenden? Weil es wirklich schwer zu debuggen ist.

Angenommen, die Instanz "bar" ist fehlgeschlagen. Frage: Welche Klasse ist fehlgeschlagen? Welchen Code sollte ich reparieren? Eine einfache Ansicht, die zu einer Schnittstelle führt, und hier endet meine Straße.

Wenn der Code stattdessen eine harte Abhängigkeit verwendet, ist es einfach, einen Fehler zu debuggen.

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

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

  //...
}

Wenn "bar" fehlschlägt, sollte ich die Klasse BarService überprüfen und auslösen.


1
Eine Klasse ist eine Blaupause zum Erstellen eines bestimmten Objekts. Andererseits ist eine Schnittstelle eine contractund definiert nur ein Verhalten, nicht die Aktion. Anstatt das eigentliche Objekt weiterzugeben, wird nur die Schnittstelle gemeinsam genutzt, damit der Verbraucher nicht auf den Rest Ihres Objekts zugreift. Auch beim Testen von Einheiten hilft es, nur das Teil zu testen, das getestet werden muss. Ich denke, mit der Zeit würden Sie seine Nützlichkeit verstehen.
Gunhan
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.