bez závislosti injectionEdit

v následujícím příkladu Java obsahuje Třída klienta proměnnou člena služby, která je inicializována konstruktorem klienta. Klient kontroluje, která implementace služby je využívána a řídí její konstrukci. V této situaci má klient prý pevně danou závislost na příkladech.

// An example without dependency injectionpublic class Client { // Internal reference to the service used by this client private ExampleService service; // Constructor Client() { // Specify a specific implementation in the constructor instead of using dependency injection service = new ExampleService(); } // Method within this client that uses the services public String greet() { return "Hello " + service.getName(); }}

Dependency injection je alternativní technika inicializovat členské proměnné spíše než explicitně vytvoření objektu služby, jak je uvedeno výše., Tento příklad můžeme upravit pomocí různých technik popsaných a ilustrovaných v níže uvedených pododdílech.

Druhy závislostí injectionEdit

Existují nejméně tři způsoby, jak klienta objekt může zobrazit odkaz na externí modul:

konstruktér vstřikování závislostí jsou poskytovány prostřednictvím klienta konstruktoru třídy. vstřikování setru klient vystavuje metodu setru, kterou injektor používá k injekci závislosti. interface Injector interface poskytuje injectorovou metodu, která vstříkne závislost do každého klienta, který mu byl předán., Klienti musí implementovat rozhraní, které vystavuje metodu setter, která přijímá závislost.

Ostatní typyedit

je možné, aby di rámce měly jiné typy injekcí než ty, které jsou uvedeny výše.

testovací rámce mohou používat i jiné typy. Některé moderní testovací rámce ani nevyžadují, aby klienti aktivně přijímali injekci závislosti, čímž se legacy code testuje. Zejména v jazyce Java je možné použít reflexi k zveřejnění soukromých atributů při testování, a tak přijímat injekce přiřazením.,

některé pokusy o inverzi kontroly neposkytují úplné odstranění závislosti,ale místo toho jednoduše nahrazují jednu formu závislosti za jinou. Obecně platí, že pokud se programátor může podívat na nic jiného než na klientský kód a říct, jaký rámec se používá, pak má klient pevně kódovanou závislost na rámci.

Konstruktoru injectionEdit

Tato metoda vyžaduje klienta poskytnout parametr v konstruktoru pro závislost.

setter injectionEdit

tato metoda vyžaduje, aby klient poskytl metodu setter pro závislost.,

interface injectionEdit

to je prostě klient publikování rozhraní role na setter metody závislostí klienta. Může být použit k určení, jak by měl vstřikovač mluvit s klientem při vstřikování závislostí.

// Service setter interface.public interface ServiceSetter { public void setService(Service service);}// Client classpublic class Client implements ServiceSetter { // Internal reference to the service used by this client. private Service service; // Set the service that this client is to use. @Override public void setService(Service service) { this.service = service; }}

Constructor injection comparisonEdit

Přednostní, když všechno závislostí může být postavena jako první, protože to může být použit k zajištění klienta objekt je vždy v platném stavu, jak protilehlý k mít některé z jeho závislostí odkazy být null (není možné nastavit)., Sama o sobě však postrádá flexibilitu, aby se její závislosti později změnily. Může to být první krok k tomu, aby byl klient neměnný, a proto byl závit Bezpečný.

Setter injection comparisonEdit

Vyžaduje klienta poskytnout setter metody pro každou závislost. To dává svobodu kdykoli manipulovat se stavem odkazů na závislost. To nabízí flexibilitu, ale pokud existuje více než jedna závislost být aplikován, to je obtížné pro klienta, aby zajistily, že všechny závislosti jsou injekčně předtím, než klient může být k dispozici pro použití.,

protože tyto injekce se dějí nezávisle, neexistuje způsob, jak zjistit, kdy je vstřikovač dokončen zapojení klienta. Závislost může být ponechána null jednoduše tím, že vstřikovač nezavolá svůj setr. To nutí kontrolu, že injekce byla dokončena od okamžiku, kdy je klient sestaven, kdykoli je použit.

Rozhraní injekce comparisonEdit

výhodou rozhraní injekce je, že závislost může být zcela neznalý své klienty, přesto může stále přijímat odkaz na nového klienta a používat to, poslat odkaz-na-self zpět klientovi., Tímto způsobem se závislosti stávají injektory. Klíčem je, že injekční metoda (která by mohla být pouze klasickou metodou setru) je poskytována prostřednictvím rozhraní.

pro zavedení klienta a jeho závislostí je stále zapotřebí assembler. Assembler by se odkaz na klienta, hoď to setr rozhraní, které stanoví, že závislost, a předat ji, že závislost předmět, který by se otočit a projít odkaz-na-self zpět klientovi.,

aby injekce rozhraní měla hodnotu, musí závislost udělat něco kromě toho, že jednoduše předá odkaz na sebe. To by mohlo působit jako továrna nebo sub-assembler k vyřešení dalších závislostí, a tak abstrahovat některé detaily od hlavního assembleru. Mohlo by to být referenční počítání, aby závislost věděla, kolik klientů ji používá. V případě, že závislost udržuje sbírku klientů, to by mohlo později aplikovat je všechny s jinou instancí sebe.,

sestavení příkladůedit

ruční ruční ruční sestavení je jedním ze způsobů implementace injekce závislosti.

výše uvedený příklad konstruuje graf objektu ručně a poté jej vyvolá v jednom bodě, aby začal fungovat. Důležité je poznamenat, že tento injektor není čistý. Používá jeden z objektů, které konstruuje. Má čistě stavební vztah pouze k příkladům, ale mísí konstrukci a využití klienta. To by nemělo být běžné. Je to však nevyhnutelné., Stejně jako objektově orientovaný software potřebuje non-objektově orientované statické metody main() chcete-li začít, závislost injekčně objekt grafu potřebuje alespoň jeden (nejlépe jen jeden) vstupní bod, aby si celou věc začala.

ruční konstrukce v hlavní metodě nemusí být přímočará a může zahrnovat volání stavitelů, továren nebo jiných stavebních vzorů. To může být poměrně pokročilé a abstraktní., Linka je překročena z manuální injekce závislosti na injekci framework závislosti, jakmile je konstrukční kód již není vlastní aplikaci a je místo toho univerzální.

rámce, jako je Spring, mohou konstruovat stejné objekty a spojit je dohromady před vrácením odkazu klientovi. Veškerá zmínka o konkrétních Příkladechslužba může být přesunuta z kódu do konfiguračních dat.

rámce, jako je pružina, umožňují externalizaci detailů sestavy v konfiguračních souborech.Tento kód (výše) konstruuje objekty a spojuje je dohromady podle fazolí.xml (níže)., ExampleService je stále konstruována, i když je uvedena pouze níže. Tímto způsobem lze definovat dlouhý a složitý graf objektů a jedinou třídou uvedenou v kódu by byla třída s metodou vstupního bodu, která je v tomto případě pozdravena().

v příkladu výše klient a služba nemuseli podstoupit žádné změny, které mají být poskytnuty do jara. Mohou zůstat jednoduchými POJOs. To ukazuje, jak jaro může spojit služby a klienty, kteří zcela nevědí o jeho existenci. To nelze říci, pokud byly do tříd přidány jarní anotace., Tím, že systém udržuje anotace specifické pro jaro a volání z šíření mezi mnoha třídami, zůstává systém pouze volně závislý na jaře. To může být důležité, pokud systém hodlá přežít jaro.

volba udržet POJOs čisté nepřichází bez nákladů. Spíše než utrácet úsilí rozvíjet a udržovat komplexní konfigurační soubory, je možné jednoduše využít poznámky k označení třídy a nechat na Jaře dělat zbytek práce. Řešení závislostí může být jednoduché, pokud se řídí konvencí, jako je shoda podle typu nebo jména. To je volba konvence nad konfigurací., Je také diskutabilní, že při refaktorování na jiný rámec by odstranění specifických anotací rámce bylo triviální součástí úkolu a mnoho anotací injekce je nyní standardizováno.

@Componentpublic class ExampleService { public String getName() { return "World!"; }}

Montážní comparisonEdit

různé injector implementace (továrny, služby lokátory, a dependency injection kontejnery) nejsou tak odlišné, jak daleko, jak dependency injection se týká. Rozdíl je v tom, kde mohou být použity., Přesuňte volání do továrny nebo servisního lokátoru z klienta a do hlavního a náhle hlavního je poměrně dobrý kontejner pro vstřikování závislostí.

přesunutím veškeré znalosti vstřikovače ven, čistý Klient, bez znalosti vnějšího světa, je pozadu. Jakýkoli objekt, který používá jiné objekty, však může být považován za klienta. Objekt, který obsahuje hlavní, není výjimkou. Tento hlavní objekt nepoužívá injekci závislosti. Ve skutečnosti používá vzor vyhledávače služeb. Tomu se nelze vyhnout, protože výběr implementací služeb musí být někde proveden.,

externalizace závislostí do konfiguračních souborů tuto skutečnost nemění. To, co dělá tuto realitu součástí dobrého designu, je to, že vyhledávač služeb se nerozšíří po celé kódové základně. Je omezena na jedno místo na aplikaci. To ponechává zbytek kódové základny volný pro použití injekce závislosti na čistých klientech.

závislost Injection PatternEdit

příklady až dosud byly příliš jednoduché příklady o konstrukci řetězce., Vzor pro vstřikování závislostí je však nejužitečnější při vytváření grafu objektů, kde objekty komunikují prostřednictvím zpráv. Objekty postavené v hlavní bude trvat po celou dobu životnosti programu. Typickým vzorem je sestavení grafu a pak volání jedné metody na jednom objektu pro odeslání toku kontroly do grafu objektu. Stejně jako hlavní je vstupní bod do statického kódu, tato metoda je vstupní bod do aplikace non-statický kód.,

AngularJS exampleEdit

V AngularJS framework, existují pouze tři způsoby, součást (objekt nebo funkce) může přímo přistupovat k jeho závislosti:

  1. komponenty lze vytvořit závislost, obvykle pomocí new operátor.
  2. komponenta může vyhledat závislost odkazem na globální proměnnou.
  3. komponenta může mít závislost předána tam, kde je potřeba.

první dvě možnosti vytvoření nebo vyhledání závislostí nejsou optimální, protože mají pevný kód závislost na součásti., To ztěžuje, ne-li nemožné, upravit závislosti. To je obzvláště problematické v testech, kde je často žádoucí poskytnout falešné závislosti pro izolaci testů.

třetí možnost je nejschůdnější, protože odstraňuje odpovědnost za lokalizaci závislosti ze složky. Závislost je jednoduše předána komponentě.

Ve výše uvedeném příkladu, SomeClass nezajímá se o vytvoření nebo vyhledání přivítání závislost, to je prostě podal přivítání, když je vytvořena instance.,

to je žádoucí, ale klade odpovědnost za získání závislosti na kódu, který konstruuje SomeClass.

pro správu odpovědnosti za vytváření závislostí má každá aplikace AngularJS vstřikovač. Vstřikovač je servisní lokátor, který je zodpovědný za konstrukci a vyhledávání závislostí.

Tady je příklad použití vstřikovače služby:

Vytvořit nové vstřikovače, které mohou poskytovat komponenty definované v myModule modul a požádat naše přivítání služby od vstřikovače., (To se obvykle provádí automaticky pomocí AngularJS bootstrap).

var injector = angular.injector();var greeter = injector.get('greeter');

žádost o závislosti řeší problém tvrdého kódování, ale také to znamená, že injektor musí být předán v celé aplikaci. Průchod injektoru porušuje zákon Demetera., K nápravě tohoto, budeme používat deklarativní zápis v HTML šablony, do rukou odpovědnost za vytvoření komponenty do vstřikovače, stejně jako v tomto příkladu:

<div ng-controller="MyController"> <button ng-click="sayHello()">Hello</button></div>
function MyController($scope, greeter) { $scope.sayHello = function() { greeter.greet('Hello World'); };}

Když AngularJS sestavuje HTML, procesy ng-controller směrnice, což žádá injector vytvořit instanci správce a jeho závislosti.

injector.instantiate(MyController);

to vše se děje v zákulisí., Protože ng-controller odkládá vstřikovače vytvořit instanci třídy, může uspokojit všechny závislosti MyController bez správce vůbec věděl o vstřikovače. Aplikační kód jednoduše deklaruje závislosti, které potřebuje, aniž by se musel zabývat vstřikovačem. Toto nastavení neporušuje zákon Demetera.

C#Edit

příklad vstřikování konstruktoru, vstřikování Setru a vstřikování rozhraní na C#

Articles

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *