Fără dependență injectionEdit

În următoarele Java exemplu, Clientul clasa conține un Serviciu variabila este inițializată de către Client constructor. Clientul controlează ce implementare a serviciului este utilizată și controlează construcția acestuia. În această situație, se spune că clientul are o dependență greu codificată de ExampleService.

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

injectare Dependență este o tehnică alternativă pentru a inițializa variabila, mai degrabă decât în mod explicit crearea unui serviciu de obiect așa cum se arată mai sus., Putem ajusta acest exemplu folosind diferitele tehnici descrise și ilustrate în subsecțiunile de mai jos.

Tipuri de dependență injectionEdit

Există cel puțin trei moduri în care un client obiect poate primi o trimitere la un modul extern:

constructor de injecție dependențele sunt furnizate prin intermediul unui client de e constructorul clasei. setter injection clientul expune o metodă setter pe care injectorul o folosește pentru a injecta dependența. interface injection interfața dependenței oferă o metodă de injectare care va injecta dependența în orice client care i-a fost transmis., Clienții trebuie să implementeze o interfață care expune o metodă setter care acceptă dependența.

alte typesEdit

este posibil ca cadrele DI să aibă alte tipuri de injecție dincolo de cele prezentate mai sus.

cadrele de testare pot utiliza și alte tipuri. Unele cadre moderne de testare nu necesită nici măcar ca clienții să accepte în mod activ injecția de dependență, făcând astfel testabil codul legacy. În special, în limbajul Java, este posibil să se utilizeze reflecția pentru a face publice atributele private atunci când se testează și, astfel, să se accepte injecții prin atribuire.,unele încercări de inversare a controlului nu oferă eliminarea completă a dependenței, ci pur și simplu înlocuiesc o formă de dependență cu alta. De regulă, dacă un programator nu se poate uita decât la codul clientului și poate spune ce cadru este utilizat, atunci clientul are o dependență greu codificată de cadru.

Constructor injectionEdit

această metodă cere clientului să furnizeze un parametru într-un constructor pentru dependență.

Setter injectionEdit

această metodă cere clientului să furnizeze o metodă setter pentru dependență.,

Interface injectionEdit

acesta este pur și simplu clientul care publică o interfață de rol pentru metodele setter ale dependențelor clientului. Acesta poate fi utilizat pentru a stabili modul în care injectorul trebuie să vorbească cu clientul atunci când injectează dependențe.

// 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 de injecție comparisonEdit

de Preferat atunci când toate dependențele pot fi construite în primul rând pentru că acesta poate fi utilizat pentru a asigura clientul obiect este întotdeauna într-un stat valabil, spre deosebire de a avea unele dintre dependenței sale referințe fi null (nu poate fi stabilită)., Cu toate acestea, pe cont propriu, îi lipsește flexibilitatea de a-și schimba dependențele mai târziu. Acesta poate fi un prim pas spre a face clientul imuabil și, prin urmare, firul în siguranță.

Setter injection comparisonEdit

cere clientului să furnizeze o metodă setter pentru fiecare dependență. Acest lucru oferă libertatea de a manipula starea referințelor de dependență în orice moment. Acest lucru oferă flexibilitate, dar dacă există mai multe dependențe care trebuie injectate, este dificil pentru client să se asigure că toate dependențele sunt injectate înainte ca clientul să poată fi furnizat pentru utilizare.,deoarece aceste injecții se întâmplă independent, nu există nicio modalitate de a spune când injectorul este terminat de cablat clientul. O dependență poate fi lăsat nul pur și simplu de injector nu pentru a apela setter sale. Acest lucru forțează verificarea faptului că injecția a fost finalizată de la asamblarea clientului până la utilizarea acestuia.avantajul interface injection este că dependențele pot fi complet ignorante față de clienții lor, dar pot primi în continuare o referință la un client nou și, folosind-o, trimit o referință la sine înapoi la client., În acest fel, dependențele devin injectoare. Cheia este că metoda de injectare (care ar putea fi doar o metodă clasică de setare) este furnizată printr-o interfață.

un asamblor este încă necesar pentru a introduce clientul și dependențele acestuia. Asamblorul ar lua o referință la client, ar arunca-o la interfața setter care stabilește acea dependență și ar trece-o la acel obiect de dependență care s-ar întoarce și ar trece o referință la sine înapoi la client.,

pentru ca injecția de interfață să aibă valoare, dependența trebuie să facă ceva în plus față de simpla trecere înapoi a unei referințe la sine. Aceasta ar putea acționa ca o fabrică sau sub-asamblor pentru a rezolva alte dependențe, abstractizând astfel unele detalii din asamblorul principal. Ar putea fi numărarea referințelor, astfel încât dependența să știe câți clienți o folosesc. Dacă dependența menține o colecție de clienți, le-ar putea injecta ulterior pe toate cu o altă instanță în sine.,

Exemple de Asamblaredit

asamblarea manuală în principal cu mâna este o modalitate de implementare a injecției de dependență.

exemplul de mai sus construiește manual graficul obiect și apoi îl invocă la un moment dat pentru a începe să funcționeze. Important de reținut este că acest injector nu este pur. Folosește unul dintre obiectele pe care le construiește. Are o relație exclusiv de construcție cu ExampleService, dar amestecă construcția și utilizarea clientului. Acest lucru nu ar trebui să fie comun. Cu toate acestea, este inevitabil., La fel ca software-ul orientat obiect are nevoie de o metodă statică non-obiect orientat ca main() pentru a începe, o dependență injectat grafic obiect are nevoie de cel puțin un (preferabil doar unul) punct de intrare pentru a obține totul a început.construcția manuală în metoda principală poate să nu fie acest lucru drept înainte și poate implica apelarea constructorilor, fabricilor sau a altor modele de construcție. Acest lucru poate fi destul de avansat și abstract., Linia este traversat de manual de injectare dependență-cadru de injectare dependență odată cu construirea codul nu mai personalizate la cerere și este în schimb universal.

cadrele precum Spring pot construi aceleași obiecte și le pot conecta împreună înainte de a returna o referință la client. Toate mențiunile exemplului concretserviciul poate fi mutat de la cod la datele de configurare.

cadrele precum Spring permit externalizarea detaliilor de asamblare în fișierele de configurare.Acest cod (de mai sus) construiește obiecte și le conectează împreună în funcție de fasole.xml (de mai jos)., ExampleService este încă construit, chiar dacă este menționat doar mai jos. Un grafic obiect lung și complex poate fi definit în acest fel și singura clasă menționată în cod ar fi cea cu metoda punctului de intrare, care în acest caz este greet().în exemplul de mai sus, Clientul și serviciul nu au trebuit să sufere modificări care să fie furnizate de Spring. Li se permite să rămână simple POJOs. Acest lucru arată cum Spring poate conecta servicii și clienți care sunt complet ignoranți de existența sa. Acest lucru nu s-ar putea spune dacă adnotările de primăvară au fost adăugate la clase., Prin păstrarea adnotări specifice de primăvară și apeluri de la răspândirea printre multe clase, sistemul rămâne doar vag dependentă de primăvară. Acest lucru poate fi important dacă sistemul intenționează să supraviețuiască primăverii.

alegerea de a păstra POJOs pur nu vine fără costuri. În loc să cheltuiți efortul de a dezvolta și menține fișiere de configurare complexe, este posibil să utilizați pur și simplu adnotări pentru a marca clasele și a lăsa Spring să facă restul lucrărilor. Rezolvarea dependențelor poate fi simplă dacă urmează o convenție, cum ar fi potrivirea după tip sau după nume. Aceasta este alegerea convenție peste configurație., De asemenea, este discutabil faptul că, atunci când refactorizarea la un alt cadru, eliminarea adnotărilor specifice cadrului ar fi o parte banală a sarcinii și multe adnotări de injecție sunt acum standardizate.

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

de Asamblare comparisonEdit

diferite injector implementări (fabrici, serviciu de locatoare, și de injectare dependență containere) nu sunt atât de diferite pe cât de injectare dependență este în cauză. Ceea ce face diferența este locul în care li se permite să fie utilizate., Mutați apelurile către o fabrică sau un localizator de servicii din client și în principal și brusc principal face un container de injecție de dependență destul de bun.prin mutarea tuturor cunoștințelor despre injector, un client curat, fără cunoștințe despre lumea exterioară, este lăsat în urmă. Cu toate acestea, orice obiect care utilizează alte obiecte poate fi considerat client. Obiectul care conține main nu face excepție. Acest obiect principal nu utilizează injecția de dependență. Este de fapt, folosind modelul de localizare de servicii. Acest lucru nu poate fi evitat deoarece alegerea implementărilor de servicii trebuie făcută undeva.,externalizarea dependențelor în fișierele de configurare nu schimbă acest fapt. Ceea ce face ca această realitate să facă parte dintr-un design bun este faptul că localizatorul de servicii nu este răspândit în întreaga bază de cod. Se limitează la un loc pe aplicație. Acest lucru lasă restul bazei de cod liber să utilizeze injecția de dependență pentru a face clienți curați.

Dependency Injection PatternEdit

exemplele de până acum au fost Exemple prea simple despre construirea unui șir., Cu toate acestea, modelul de injecție dependență este cel mai util atunci când construirea unui grafic obiect în cazul în care obiectele comunica prin mesaje. Obiecte construite în principal va dura pentru durata de viață a programului. Modelul tipic este de a construi graficul și apoi apelați o metodă pe un obiect pentru a trimite fluxul de control în graficul obiect. La fel de principal este punctul de intrare la codul static, această metodă este punctul de intrare la codul non-static al aplicațiilor.,

AngularJS exampleEdit

În AngularJS-cadru, există doar trei moduri de o componentă (obiect sau funcție) pot accesa direct dependențele sale:

  1. componenta poate crea dependență, de obicei folosind new operator.
  2. componenta poate căuta dependența, referindu-se la o variabilă globală.
  3. componenta poate avea dependența transmisă acolo unde este nevoie.primele două opțiuni de creare sau căutare a dependențelor nu sunt optime, deoarece codifică greu dependența de componentă., Acest lucru face dificilă, dacă nu imposibilă, modificarea dependențelor. Acest lucru este deosebit de problematic în teste, unde este adesea de dorit să se furnizeze dependențe simulate pentru izolarea testelor.a treia opțiune este cea mai viabilă, deoarece elimină responsabilitatea localizării dependenței de componentă. Dependența este pur și simplu înmânată componentei.

    în exemplul de mai sus, SomeClass nu este preocupat de crearea sau localizarea dependenței greeter, este pur și simplu înmânat greeter atunci când este instanțiat.,

    Acest lucru este de dorit, dar pune responsabilitatea de a pune mâna pe dependența de codul care construiește SomeClass.pentru a gestiona responsabilitatea creării dependenței, fiecare aplicație AngularJS are un injector. Injectorul este un localizator de servicii care este responsabil pentru construcția și căutarea dependențelor.

    Iată un exemplu de utilizare a serviciului injector:

    creați un nou injector care poate furniza componentele definite în modulul myModule și solicitați serviciul nostru greeter de la injector., (Acest lucru se face de obicei în mod automat de Bootstrap AngularJS).

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

    Cere dependențe rezolvă problema de codificare greu, dar înseamnă de asemenea că injectorul trebuie să fi trecut de-a lungul aplicația. Trecerea injectorului încalcă legea lui Demeter., Pentru a remedia acest lucru, vom folosi o declarative notație în HTML template-uri, să predea responsabilitatea de a crea componente de la injector, ca în acest exemplu:

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

    Când AngularJS compilează HTML, procesele it ng-controller directiva, care, la rândul său solicită injector pentru a crea o instanță a operatorului și dependențele sale.

    injector.instantiate(MyController);

    Acest lucru se face în spatele scenei., Deoarece ng-controller amână la injectorul de a instantia clasa, ea poate satisface toate dependențele de MyController fără ca operatorul să știe vreodată despre injector. Codul aplicației declară pur și simplu dependențele de care are nevoie, fără a fi nevoie să se ocupe de injector. Această configurație nu încalcă legea lui Demeter.

    c # Edit

    exemplu de injecție Constructor, injecție Setter și injecție interfață pe C#

Articles

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *