Wstrzykiwanie zależności (Dependency Injection)

W tym wpisie przybliżę Ci jeden z najważniejszych wzorców w programowaniu, który jest niezależny od języka – wstrzykiwanie zależności.

Wstrzykiwanie zależności – prosty przykład

Załóżmy, że mamy dom, a w nim okna:

public class House {

  List<Window> windows = new ArrayList<>();

  public static void main(String[] args) {
  
  }
}

Przez okno możemy zerknąć i zobaczyć, jaką mamy pogodę.

class Window {

   private Weather weather;

   public Window() {
       this.weather = new Weather();
   }
 
   public void lookOut() {
       System.out.println(this.weather.description);
   }

}
public class Weather {

   private static Random random = new Random(System.currentTimeMillis());
   
   public String description;
   
   public Weather() {

       switch(random.nextInt(4)) {
           case 0:
              this.description = "Pada deszcz";
              break;
           case 1:
              this.description = "Świeci słońce";
              break;
           case 2:
              this.description = "Pada śnieg";
              break;
           case 4:
              this.description = "Wieje wiatr";
              break;
       }
   
   }
}

Następnie w klasie House utwórzmy konstruktor, a w nim cztery okna. Później dodajmy metodę, która wypisze nam jaka jest za nimi pogoda.

public class House {

  List<Window> windows = new ArrayList<>();

  public House() {
      windows.add(new Window());
      windows.add(new Window());
      windows.add(new Window());
      windows.add(new Window());
     
  }

  public void look() {

     for(Window window : windows) {
         window.lookOut();
     }
  }

  public static void main(String[] args) {
   
      
  }
}

Teraz w metodzie main zbudujmy nowy dom i sprawdźmy pogodę.

public class House {

  List<Window> windows = new ArrayList<>();

  public House() {
      windows.add(new Window());
      windows.add(new Window());
      windows.add(new Window());
      windows.add(new Window());
     
  }

  public void look() {

     for(Window window : windows) {
         window.lookOut();
     }
  }

  public static void main(String[] args) {
     House house = new House();
     house.look();
  }
}

Gdy odpalimy nasz program okaże się, że za każdym oknem jest inna pogoda, co jest dość niepokojące.

Dzieje się tak dlatego, że w każdym z okien tworzymy nowy obiekt odpowiadający za pogodę, przez co za każdym razem losowany jest nowy opis.

W takiej sytuacji mówimy, że klasa Weather jest zależnością klasy Window.

Tutaj z pomocą przyjdzie nam dependencji injection, czyli wstrzykiwanie zależności.

Mianowicie nie będziemy tworzyć obiektu Weather w każdym oknie, lecz będzie on przekazywany do konstruktora z zewnątrz. Takie przekazywanie zależności z zewnątrz nazywamy wstrzykiwaniem.

class Window {

   private Weather weather;

   public Window(Weather weather) {
       this.weather = weather;
   }
 
   public void lookOut() {
       System.out.println(this.weather.description);
   }

}

Następnie nowy obiekt odpowiadający za pogodę tworzymy w miejscu gdzie tworzymy nowe okna, czyli w tym wypadku w domu. My jednak przeniesiemy to jeszcze wyżej. Nie ma sensu, by w trakcie budowy domu tworzyć pogodę bo jest to twór niezależny.

public class House {

  List<Window> windows = new ArrayList<>();

  public House(Weather weather) {
      windows.add(new Window(weather));
      windows.add(new Window(weather));
      windows.add(new Window(weather));
      windows.add(new Window(weather));
     
  }

  public void look() {

     for(Window window : windows) {
         window.lookOut();
     }
  }

  public static void main(String[] args) {
     Weather weather = new Weather();
     House house = new House(weather);
     house.look();
  }
}

I w tym momencie za każdym z okien panuje taka sama pogoda. Wszystkie okna używają w swoich operacjach tego samego obiektu odpowiedzialnego za pogodę, czyli tego wstrzykniętego w konstruktorze klasy House

Jest to tak zwane wstrzykiwanie poprzez konstruktor.

Istnieje jeszcze drugi typ wstrzykiwania – poprzez metodę.

Pogoda ma to do siebie, że lubi się zmieniać. Ustawianie jej na sztywno w konstruktorze nie wystarcza, więc musimy mieć możliwość jej zmiany.

public class House {

  List<Window> windows = new ArrayList<>();

  public House(Weather weather) {
      windows.add(new Window(weather));
      windows.add(new Window(weather));
      windows.add(new Window(weather));
      windows.add(new Window(weather));
     
  }

  public void setWeather(Weather weather) { 
      this.weahter = weather;
  }

  public void look() {

     for(Window window : windows) {
         window.lookOut();
     }
  }

  public static void main(String[] args) {
     Weather weather = new Weather();
     House house = new House(weather);
     house.look();
  }
}

Czyli stosujemy najprostszego w świecie settera i mamy szumnie brzmiące wstrzykiwanie poprzez metodę 🙂

I to tyle. Tylko tyle i aż tyle. Wstrzykiwanie zależności bez żadnych dodatków. Frameworki takie jak Spring ułatwiają wstrzykiwanie zależności – poprzez użycie DI wraz ze wzorcem object pool oraz adnotacjami. Dzięki tym dwóm dodatkom dzieje się “automagia” natomiast sedno wstrzykiwania zależności działa tak jak przedstawione powyżej, tylko w tle.

By być na bieżąco i mieć realny wpływ na tematykę tworzonych artykułów zapraszam do dołączenia do mojego newslettera.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *