design-patterns la dependency - Cos'è l'iniezione di dipendenza?




15 Answers

Fondamentalmente, invece di fare in modo che gli oggetti creino una dipendenza o chiedano a un oggetto factory di crearne uno, passano esternamente le dipendenze necessarie all'oggetto e lo rendi il problema di qualcun altro. Questo "qualcuno" è o un oggetto più in alto sul grafico delle dipendenze, o un injector delle dipendenze (framework) che costruisce il grafico delle dipendenze. Una dipendenza mentre la sto usando qui è qualsiasi altro oggetto a cui l'oggetto corrente deve avere un riferimento.

Uno dei principali vantaggi dell'iniezione di dipendenza è che può rendere più semplici i test. Supponiamo di avere un oggetto che nel suo costruttore fa qualcosa del tipo:

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

Questo può essere problematico quando tutto ciò che si vuole fare è eseguire alcuni test unitari su SomeClass, specialmente se myObject è qualcosa che ha un accesso complesso al disco o alla rete. Quindi ora stai cercando di deridere myObject ma in qualche modo intercettando la chiamata factory. Difficile. Invece, passare l'oggetto come argomento al costruttore. Ora hai spostato il problema altrove, ma il test può diventare molto più semplice. Basta fare un dummy myObject e farlo passare. Il costruttore ora assomiglia un po 'a:

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

Questo è uno stile di iniezione delle dipendenze, tramite il costruttore. Sono possibili diversi meccanismi.

  • Come notato nei commenti, un'alternativa comune è definire un costruttore del nulla-fare e far sì che le dipendenze vengano iniettate tramite i setter di proprietà (h / t @MikeVella).
  • Martin Fowler documenta una terza alternativa (h / t @MarcDix), in cui le classi implementano esplicitamente un'interfaccia per le dipendenze che desiderano iniettare.

Quando non si utilizza l'iniezione di dipendenza (come nelle classi che fanno troppo lavoro nei loro costruttori ecc.), Tende a diventare molto più difficile isolare i componenti nei test unitari.

Nel 2013, quando ho scritto questa risposta, questo era uno dei temi principali del Blog di test di Google . Questo rimane il più grande vantaggio per me, poiché potresti non aver sempre bisogno della flessibilità extra nel tuo progetto di run-time (ad esempio, per localizzatore di servizi o modelli simili), ma spesso devi essere in grado di isolare le tue classi durante i test.

injection c#

Sono già state pubblicate diverse domande con domande specifiche sull'iniezione delle dipendenze , come quando usarlo e quali strutture ci sono per esso. Però,

Qual è l'iniezione di dipendenza e quando / perché dovrebbe o non dovrebbe essere utilizzata?




Ho trovato questo divertente esempio in termini di accoppiamento lento :

Ogni applicazione è composta da molti oggetti che collaborano tra loro per eseguire alcune cose utili. Tradizionalmente ogni oggetto è responsabile per ottenere i propri riferimenti agli oggetti dipendenti (dipendenze) con cui collabora. Questo porta a classi altamente accoppiate e codice difficile da testare.

Ad esempio, considera un oggetto Car .

Una Car dipende da ruote, motore, carburante, batteria, ecc. Tradizionalmente definiamo la marca di tali oggetti dipendenti insieme alla definizione dell'oggetto Car .

Senza Iniezione di Dipendenza (DI):

class Car{
  private Wheel wh = new NepaliRubberWheel();
  private Battery bt = new ExcideBattery();

  //The rest
}

Qui, l'oggetto Car è responsabile della creazione degli oggetti dipendenti.

Cosa succede se si desidera modificare il tipo di oggetto dipendente, ad esempio Wheel , dopo le NepaliRubberWheel() iniziali di NepaliRubberWheel() ? Abbiamo bisogno di ricreare l'oggetto Car con la sua nuova dipendenza, diciamo ChineseRubberWheel() , ma solo il costruttore di Car può farlo.

Allora cosa ci fa la Dependency Injection per ...?

Quando si utilizza l'iniezione di dipendenza, agli oggetti vengono fornite le loro dipendenze in fase di esecuzione piuttosto che il tempo di compilazione (tempo di produzione dell'auto) . In modo che ora possiamo cambiare la Wheel quando vogliamo. Qui, la dependency ( wheel ) può essere iniettata in Car in fase di esecuzione.

Dopo aver usato l'iniezione di dipendenza:

Qui, stiamo iniettando le dipendenze (ruota e batteria) in fase di esecuzione. Da qui il termine: Iniezione di dipendenza.

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

Fonte: comprensione dell'iniezione di dipendenza




La risposta accettata è buona, ma vorrei aggiungere che DI è molto simile al classico che evita costanti hardcoded nel codice.

Quando si utilizzano alcune costanti come il nome di un database, lo si sposta rapidamente dall'interno del codice in un file di configurazione e si passa una variabile che contiene quel valore nel punto in cui è necessario. La ragione per farlo è che queste costanti di solito cambiano più frequentemente rispetto al resto del codice. Ad esempio se desideri testare il codice in un database di test.

DI è analogo a questo nel mondo della programmazione orientata agli oggetti. I valori lì invece dei costanti costanti sono oggetti interi, ma la ragione per spostare il codice che li crea fuori dal codice di classe è simile - gli oggetti cambiano più frequentemente del codice che li usa. Un caso importante in cui tale cambiamento è necessario sono i test.




Proviamo un semplice esempio con le classi di auto e motori , qualsiasi auto ha bisogno di un motore per andare ovunque, almeno per ora. Quindi sotto come apparirà il codice senza iniezione di dipendenza.

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!");
    }
}

E per istanziare la classe Car useremo il prossimo codice:

Car car = new Car();

Il problema con questo codice che abbiamo strettamente associato a GasEngine e se decidiamo di cambiarlo in ElectricityEngine, allora dovremo riscrivere la classe Car. E più grande è l'applicazione, più problemi e mal di testa dovremo aggiungere e usare un nuovo tipo di motore.

In altre parole, con questo approccio, la nostra classe Car di alto livello dipende dalla classe GasEngine di livello inferiore che viola il principio di inversione delle dipendenze (DIP) da SOLID. Il DIP suggerisce che dovremmo dipendere dalle astrazioni, non dalle lezioni concrete. Quindi per soddisfare questo, introduciamo l'interfaccia IEngine e riscriviamo il codice come di seguito:

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

Ora la nostra classe Car dipende solo dall'interfaccia IEngine, non da un'implementazione specifica del motore. Ora, l'unico trucco è come creare un'istanza della macchina e dargli una classe concreta di motore come GasEngine o ElectricityEngine. Ecco dove entra in gioco l' iniezione di dipendenza .

   Car gasCar = new Car(new GasEngine());
   gasCar.Run();
   Car electroCar = new Car(new ElectricityEngine());
   electroCar.Run();

Qui fondamentalmente iniettiamo (passiamo) la nostra dipendenza (istanza del motore) al costruttore di automobili. Così ora le nostre classi hanno un accoppiamento lento tra gli oggetti e le loro dipendenze, e possiamo facilmente aggiungere nuovi tipi di motori senza cambiare la classe Car.

Il principale vantaggio di Dependency Injection è che le classi sono più liberamente accoppiate, perché non hanno dipendenze hard-coded. Questo segue il principio di inversione della dipendenza, che è stato menzionato sopra. Invece di fare riferimento a specifiche implementazioni, le classi richiedono le astrazioni (di solito le interfacce ) che vengono fornite loro quando la classe è costruita.

Quindi alla fine l' iniezione di dipendenza è solo una tecnica per ottenere un accoppiamento lento tra gli oggetti e le loro dipendenze. Anziché creare direttamente delle dipendenze di cui la classe ha bisogno per eseguire le proprie azioni, le dipendenze vengono fornite alla classe (il più delle volte) tramite l'iniezione del costruttore.

Anche quando abbiamo molte dipendenze è molto buona pratica usare i contenitori di Inversion of Control (IoC) che possiamo dire quali interfacce devono essere mappate su quali implementazioni concrete per tutte le nostre dipendenze e possiamo far sì che risolva quelle dipendenze per noi quando costruisce il nostro oggetto. Ad esempio, potremmo specificare nella mappatura per il contenitore IoC che la dipendenza IEngine debba essere mappata alla classe GasEngine e quando chiediamo al contenitore IoC un'istanza della nostra classe Car , essa costruirà automaticamente la nostra classe Car con una dipendenza GasEngine passato dentro

AGGIORNAMENTO: Ho assistito recentemente a un corso su EF Core da Julie Lerman e mi è anche piaciuta la sua breve definizione su DI.

L'iniezione di dipendenza è uno schema che consente alla tua applicazione di iniettare oggetti al volo per le classi che ne hanno bisogno, senza forzare le classi a essere responsabili di tali oggetti. Consente al codice di essere accoppiato in modo più semplice e Entity Framework Core si collega a questo stesso sistema di servizi.




Non "iniezione di dipendenza" significa solo l'uso di costruttori parametrizzati e di setter pubblici?

L'articolo di James Shore mostra i seguenti esempi per il confronto .

Costruttore senza iniezione di dipendenza:

public class Example { 
  private DatabaseThingie myDatabase; 

  public Example() { 
    myDatabase = new DatabaseThingie(); 
  } 

  public void doStuff() { 
    ... 
    myDatabase.getData(); 
    ... 
  } 
} 

Costruttore con iniezione di dipendenza:

public class Example { 
  private DatabaseThingie myDatabase; 

  public Example(DatabaseThingie useThisDatabaseInstead) { 
    myDatabase = useThisDatabaseInstead; 
  }

  public void doStuff() { 
    ... 
    myDatabase.getData(); 
    ... 
  } 
}



Per rendere il concetto di dipendenza da iniezione semplice da capire. Prendiamo un esempio di pulsante di commutazione per attivare / disattivare una lampadina.

Senza iniezione di dipendenza

Switch ha bisogno di sapere in anticipo a quale lampadina sono collegato (dipendenza hard-coded). Così,

Switch -> PermanentBulb // switch è direttamente collegato alla lampadina permanente, test non è possibile facilmente

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

Con iniezione di dipendenza

Lo switch sa solo che ho bisogno di accendere / spegnere qualsiasi Bulb mi viene passato. Così,

Switch -> Bulb1 OR Bulb2 OR NightBulb (dipendenza iniettata)

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

Modifica di James Example per Switch e Bulb:

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



Cos'è l'iniezione di dipendenza?

Iniezione di dipendenza (DI) significa disaccoppiare gli oggetti che dipendono l'uno dall'altro. Dire che l'oggetto A dipende dall'oggetto B, quindi l'idea è di separare questi oggetti l'uno dall'altro. Non abbiamo bisogno di codificare l'oggetto con una nuova parola chiave piuttosto di condividere le dipendenze con gli oggetti in fase di runtime, nonostante il tempo di compilazione. Se parliamo

Come funziona la Dependency Injection in primavera:

Non è necessario codificare l'oggetto con una nuova parola chiave, piuttosto definire la dipendenza del bean nel file di configurazione. Il contenitore della molla sarà responsabile per il collegamento di tutti.

Inversion of Control (IOC)

Il CIO è un concetto generale e può essere espresso in molti modi diversi e l'iniezione di dipendenza è un esempio concreto di IOC.

Due tipi di iniezione delle dipendenze:

  1. Costruttore di iniezione
  2. Iniezione Setter

1. Iniezione di dipendenza basata sul costruttore:

Il DI basato sul costruttore viene eseguito quando il contenitore richiama un costruttore di classi con un numero di argomenti, ognuno dei quali rappresenta una dipendenza da un'altra 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. Iniezione di dipendenze basata su setter:

La DI basata su Setter viene eseguita dai metodi di richiamo di chiamata del contenitore sui bean dopo aver richiamato un metodo di costruzione senza argomenti o un metodo statico senza argomento per istanziare il bean.

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

NOTA: è una buona regola empirica utilizzare gli argomenti del costruttore per le dipendenze e i setter obbligatori per le dipendenze opzionali. Si noti che se si utilizza annotazione basata su annotazione @Required su un setter, è possibile utilizzare i setter come dipendenze obbligatorie.




Tutte le risposte di cui sopra sono buone, il mio obiettivo è quello di spiegare il concetto in modo semplice in modo che chiunque non abbia una conoscenza di programmazione possa anche capire il concetto

L'iniezione di dipendenza è uno degli schemi di progettazione che ci aiuta a creare sistemi complessi in modo più semplice.

Possiamo vedere un'ampia varietà di applicazione di questo modello nella nostra vita quotidiana. Alcuni esempi sono registratore a nastro, VCD, CD Drive, ecc.

L'immagine sopra è un'immagine del registratore a nastro portatile Reel-to-reel, metà del 20 ° secolo. Source .

L'intenzione principale di un registratore è quella di registrare o riprodurre il suono. Mentre si progetta un sistema, è necessario un reel per registrare o riprodurre suoni o musica. possiamo posizionare la bobina all'interno della macchina o possiamo fornire un gancio per la bobina dove può essere posizionato. Se optiamo per la seconda che sta posizionando un gancio per bobina, stiamo ottenendo un ulteriore vantaggio di riprodurre qualsiasi musica cambiando la bobina. e anche riducendo la funzione riproducendo qualsiasi cosa nella bobina.

I principali benefici che abbiamo ottenuto utilizzando l'iniezione di dipendenza.

  • Elevata coesione e accoppiamento libero.
  • Esternalizzare la dipendenza e guardare solo alla responsabilità.
  • Fare cose come componenti e combinare per formare un sistema di grandi dimensioni con elevate capacità.
  • Aiuta a sviluppare componenti di alta qualità poiché sono sviluppati in modo indipendente e sono adeguatamente testati.
  • Aiuta a sostituire il componente con un altro se uno fallisce.

Ora un giorno questi concetti costituiscono la base di strutture ben note nel mondo della programmazione. The Spring Angular ecc sono i ben noti framework software costruiti sulla cima di questo concetto

L'injection dependance è un pattern utilizzato per creare istanze di oggetti su cui altri oggetti fanno affidamento senza sapere in fase di compilazione quale classe verrà utilizzata per fornire tale funzionalità o semplicemente il modo di iniettare le proprietà a un oggetto è chiamato injection dependency.

Esempio di iniezione di dipendenza

In precedenza stiamo scrivendo un codice come questo

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

Con l'iniezione di dipendenza, l'iniettore di dipendenza decollerà per noi l'istanziazione

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

Puoi anche leggere

Differenza tra inversione di controllo e iniezione di dipendenza




Penso che poiché tutti hanno scritto per DI, mi permetta di fare alcune domande ...

  1. Quando si dispone di una configurazione di DI in cui tutte le implementazioni effettive (non le interfacce) che verranno immesse in una classe (ad esempio i servizi di un controller), perché non si tratta di una sorta di hard-coding?
  2. Cosa succede se voglio cambiare l'oggetto in fase di runtime? Ad esempio, la mia configurazione dice già quando istanzio MyController, inject per FileLogger come ILogger. Ma potrei voler iniettare DatabaseLogger.
  3. Ogni volta che voglio cambiare gli oggetti di cui il mio AClass ha bisogno, ho bisogno di esaminare due aspetti: la classe stessa e il file di configurazione. Come fa a rendere la vita più facile?
  4. Se Aproperty of AClass non viene iniettato, è più difficile deriderlo?
  5. Tornando alla prima domanda. Se l'utilizzo di new object () non è corretto, come mai iniettiamo l'implementazione e non l'interfaccia? Penso che molti di voi stiano dicendo che stiamo effettivamente iniettando l'interfaccia, ma la configurazione ti permette di specificare l'implementazione di quell'interfaccia .. non in fase di esecuzione .. è hardcoded durante la compilazione.

Questo è basato sulla risposta @Adam N pubblicato.

Perché PersonService non deve più preoccuparsi di GroupMembershipService? Hai appena menzionato GroupMembership ha più cose (oggetti / proprietà) da cui dipende. Se GMService fosse richiesto in PService, lo avresti come proprietà. Puoi deriderlo indipendentemente dal fatto che tu l'abbia iniettato o meno. L'unica volta che mi piacerebbe che fosse iniettata è se GMService avesse classi figlio più specifiche, cosa che non sapresti fino al runtime. Allora dovresti iniettare la sottoclasse. O se volessi usarlo come singleton o come prototipo. Per essere onesti, il file di configurazione ha tutto ciò che è hardcoded per quanto riguarda la sottoclasse di un tipo (interfaccia) che verrà iniettata durante la compilazione.

MODIFICARE

Un bel commento di Jose Maria Arranz su DI

DI aumenta la coesione eliminando ogni necessità di determinare la direzione della dipendenza e scrivere qualsiasi codice di colla.

Falso.La direzione delle dipendenze è in formato XML o come annotazioni, le tue dipendenze sono scritte come codice XML e annotazioni. XML e annotazioni SONO il codice sorgente.

DI riduce l'accoppiamento rendendo tutti i componenti modulari (cioè sostituibili) e presentano interfacce ben definite l'una con l'altra.

Falso. Non è necessario un framework DI per creare un codice modulare basato su interfacce.

Informazioni sulla sostituzione: con un semplice archivio .properties e Class.forName puoi definire quali classi possono cambiare. Se QUALSIASI classe del codice può essere modificata, Java non fa per te, usa un linguaggio di scripting. A proposito: le annotazioni non possono essere cambiate senza ricompilare.

A mio parere c'è un solo motivo per le strutture DI: riduzione della piastra della caldaia. Con un sistema factory ben fatto puoi fare lo stesso, più controllato e più prevedibile come il tuo framework DI preferito, i framework DI promettono la riduzione del codice (XML e le annotazioni sono anche codice sorgente). Il problema è che questa riduzione della piastra della caldaia è reale solo in casi molto semplici (un'istanza per classe e simili), a volte nel mondo reale la scelta dell'oggetto di servizio appropriato non è facile come mappare una classe a un oggetto singleton.




So che ci sono già molte risposte, ma ho trovato questo molto utile: http://tutorials.jenkov.com/dependency-injection/index.html

Nessuna dipendenza:

public class MyDao {

  protected DataSource dataSource =
    new DataSourceImpl("driver", "url", "user", "password");

  //data access methods...
  public Person readPerson(int primaryKey) {...}

}

Dipendenza:

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

}

Si noti come l' DataSourceImplistanziazione viene spostata in un costruttore. Il costruttore prende quattro parametri che sono i quattro valori necessari per DataSourceImpl. Sebbene la MyDaoclasse dipenda ancora da questi quattro valori, non soddisfa più queste dipendenze. Sono forniti da qualsiasi classe che crea MyDaoun'istanza.




Esempio, abbiamo 2 classi Cliente Service. ClientuseràService

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

Senza iniezione di dipendenza

Modo 1)

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

Via 2)

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

Modo 3)

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

1) 2) 3) Utilizzo

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

vantaggi

  • Semplice

svantaggi

  • Difficile per la Clientclasse di test
  • Quando cambiamo il Servicecostruttore, dobbiamo cambiare il codice in tutti gli Serviceoggetti di creazione del luogo

Utilizzare l'iniezione di dipendenza

Modo 1) Iniezione del costruttore

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

utilizzando

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

Modo 2) Iniezione settetta

public class Client {
    Service service;

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

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

utilizzando

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

Way 3) Iniezione dell'interfaccia

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

===

Ora, questo codice è già seguito Dependency Injectioned è più facile per la Clientclasse di test .
Tuttavia, usiamo ancora new Service()molto tempo e non è buono quando cambio Servicecostruttore. Per prevenirlo, possiamo usare l'iniettore DI come
1) Semplice manualeInjector

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

utilizzando

Service service = Injector.provideService();

2) Usa libreria: per Android dagger2

vantaggi

  • Fai il test più facile
  • Quando cambi Service, devi solo cambiarlo nella classe Injector
  • Se usi l'uso Constructor Injection, quando guardi il costruttore di Client, vedrai quante dipendenze della Clientclasse

svantaggi

  • Se si usa use Constructor Injection, l' Serviceoggetto viene creato quando viene Clientcreato, a volte si usa la funzione in Clientclasse senza uso, Servicequindi la creazione Serviceviene sprecata

Definizione iniezione di dipendenza

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

Una dipendenza è un oggetto che può essere utilizzato ( Service)
Un'iniezione è il passaggio di una dipendenza ( Service) a un oggetto dipendente ( Client) che lo userebbe







Dipendenza Iniezione (DI) è uno dei modelli di progettazione, che utilizza la caratteristica di base di OOP - la relazione in un oggetto con un altro oggetto. Mentre l'ereditarietà eredita un oggetto per rendere più complesso e specifico un altro oggetto, relazione o associazione crea semplicemente un puntatore a un altro oggetto da un oggetto usando l'attributo. La potenza di DI è in combinazione con altre funzionalità di OOP come le interfacce e il codice nascosto. Supponiamo, abbiamo un cliente (abbonato) nella biblioteca, che può prendere in prestito solo un libro per semplicità.

Interfaccia del libro:

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

Quindi possiamo avere molti tipi di libri; uno di tipo è finzione:

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

Ora l'abbonato può avere un'associazione con il libro:

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

}

}

Tutte le tre classi possono essere nascoste per la sua implementazione. Ora possiamo usare questo codice per 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();
}
}

Esistono molti modi diversi per utilizzare l'iniezione di dipendenza. È possibile combinarlo con Singleton, ecc., Ma in realtà è solo un'associazione realizzata creando attributi di tipo di oggetto all'interno di un altro oggetto. L'utilità è solo e solo nella funzionalità, quel codice, che dovremmo scrivere ancora e ancora, è sempre preparato e fatto per noi avanti. Questo è il motivo per cui DI è così strettamente legato a Inversion of Control (IoC) che significa che il nostro programma passa a controllare un altro modulo in esecuzione, che fa le iniezioni di bean al nostro codice. (Ogni oggetto, che può essere iniettato può essere firmato o considerato come un bean.) Ad esempio in primavera viene fatto creando e inizializzando ApplicationContextcontenitore, che funziona per noi. Semplicemente nel nostro codice creiamo il contesto e invochiamo l'inizializzazione dei bean. In quel momento l'iniezione è stata eseguita automaticamente.




L'iniezione di dipendenza è il cuore del concetto correlato a Spring Framework. Mentre la creazione della struttura di qualsiasi molla di progetto può svolgere un ruolo vitale, e qui l'iniezione di dipendenza arriva nel lanciatore.

In realtà, supponiamo che in java tu abbia creato due classi diverse come classe A e classe B, e qualunque sia la funzione disponibile in classe B che vuoi usare in classe A, allora in quel momento può essere usata l'iniezione di dipendenza. dove puoi cestinare l'oggetto di una classe in un'altra, nello stesso modo in cui puoi iniettare un'intera classe in un'altra classe per renderla accessibile. in questo modo la dipendenza può essere superata.

L'INIEZIONE DELLA DIPENDENZA È SEMPLICEMENTE INCARICATA DI DUE CLASSI E ALLO STESSO TEMPO MANTENENDO SEPARATI.




L'iniezione di dipendenza è un tipo di implementazione del principio di " inversione del controllo " su cui si basa la costruzione di quadri.

I framework come indicato in "Design Pattern" di GoF sono classi che implementano la principale logica di controllo del flusso sollevando lo sviluppatore a farlo, in questo modo i Framework realizzano l'inversione del principio di controllo.

Un modo per implementare come tecnica, e non come gerarchia di classi, questo principio di IoC è solo Iniezione di dipendenza.

DI consiste principalmente nel delegare la mappatura delle istanze delle classi e il riferimento al tipo di tali istanze, in una "entità" esterna: un oggetto, una classe statica, un componente, una struttura, ecc ...

Le istanze delle classi sono le " dipendenze ", l'associazione esterna del componente chiamante con l'istanza della classe attraverso il riferimento è "l' iniezione ".

Ovviamente è possibile implementare questa tecnica in molti modi come si vuole dal punto di vista OOP, vedere ad esempio l' iniezione del costruttore , l' iniezione setter , l' iniezione dell'interfaccia .

Delegare una terza parte per svolgere l'attività di abbinare un riferimento a un oggetto è molto utile quando si desidera separare completamente un componente che richiede alcuni servizi dalla stessa implementazione di servizi.

In questo modo, quando si progettano i componenti, è possibile concentrarsi esclusivamente sulla loro architettura e sulla loro logica specifica, affidandosi alle interfacce per la collaborazione con altri oggetti senza preoccuparsi di alcun tipo di modifica dell'implementazione degli oggetti / servizi utilizzati, anche se lo stesso oggetto si sta utilizzando sarà totalmente sostituito (ovviamente rispettando l'interfaccia).




Related