Zastosowanie
Wstrzykiwanie zależności
(ang. Dependency Injection
) (wzorzec architektoniczny) jest wzorcem, który pozwala na eliminacje bezpośrednich zależności między elementami systemu. Wzorzec ten jest realizacją paradygmatu Odwrócenie Sterowania
(ang. Inversion of Control
), który polega na zamianie odpowiedzialności kodu, tzn. to kod frameworka wywołuje kod programisty. Dzięki podejściu odwrócenia zależności
testowanie jest ułatwione ze względu na modularność i możliwe wstrzykiwanie zaślepek (mock
) do testowanego kodu. Realizacja wzorca następuje poprzez przekazanie zainicjalizowanych obiektów do klas, które z nich korzystają, dzięki czemu komponenty są ze sobą luźno powiązane (loose coupling
) - nie przejmują odpowiedzialności innych obiektów. Wstrzykiwanie zależności
może odbywać się m.in. poprzez konstruktor (Constructor Injection
, metodę set (Setter Injection
), interfejs (Interface Injection
) czy też refleksje (Field Injection
). Ponadto można wykorzystać tzw. Kontener DI
(DI Container
), który przejmuje odpowiedzialność inicjalizowania i wstrzykiwania obiektów w odpowiednie miejsca w odpowiednim czasie pod warunkiem zdefiniowania reguł powiązań.
Ograniczenia
Korzystając ze Wstrzykiwanie zależności
należy mieć na uwadze, że zastosowany w sposób nieumiejętny może doprowadzić do tworzenia cyklicznych zależności co jest sygnałem, że jakieś klasy nie spełniają zasady pojedynczej odpowiedzialności. Istnieje także ryzyko stworzenia super klasy poprzez wstrzyknięcie zbyt dużej ilości zależności. Z uwagi na możliwe zagrożenia refleksja nie jest zalecena do realizacji Wstrzykiwania zależności
.
Użycie
Ze względu na swoją charakterystykę i spełnienie trzech zasad SOLID
użycie Wstrzykiwania zależności
wydaje się naturalnym sposobem tworzenia większości aplikacji. Znacząco ułatwia testowanie, utrzymanie i rozwój kodu. Niektóre architektury realizujące paradygmat Odwrócenia terowania
wymuszają użycie Wstrzykiwania zależności
(np. Spring
).
Implementacja
Instancje klas, które mają zostać przekazane jako zależności do innego obiektu, są tworzone na zewnątrz poza jego ciałem. Wstrzyknięcie utworzonych zależności następuje poprzez konstruktor docelowego obiektu oraz jego metody.
Poniższy listing przedstawia realizacja wzorca na trzy sposoby.
Tak stworzone klasy mogą zostać zainicjalizowane różnymi obiektami typu Dependency1
i Dependency2
, co przedstawia poniższy listing.
Poniższy listing przedstawia implementacje klasy o podobnych właściwościach bez użycia wzorca.
Jak łatwo zauważyć obiekty klas Dependency1
oraz Dependency2
przyjmują jeden stan zgodny z wewnętrzną implementacją klasy WithoutInjection
co mocno wiąże zależności tej klasy.
Przykład
W wielu miejscach aplikacji zachodzi potrzeba logowania przepływu operacji, interakcji użytkownika oraz napotkanych błędów. W tym celu używane są obiekty typu Logger
. Jeśli użytkownik jest podłączony do internetu to logi wysyłane są bezpośrednio na serwery. W przeciwnym razie logi zapisywane są do pliku w pamięci urządzenia. Działanie aplikacji jest poddawane testom, zgodnie z którymi proces logowania ma zostać wyjęty z testów komponentów systemu. W tym celu tworzona jest zaślepka. Poniższy listing przedstawia implementacje komponentu ComponentWithLogs
wykorzystującego Wstrzykiwania zależności
przez konstruktor oraz logerów aplikacji.
Użycie Wstrzykiwania zależności
logerów dla komponentu ComponentWithLogs
aplikacji może odbywać się w nasępujący sposób.
Biblioteki
Popularnym frameworkiem dla Androida
realizujący wstrzykiwanie zależności jest Dagger 2
. Jest to Kontener DI
, który ułatwia wstrzykiwanie zależności w całej aplikacji. Innym przykładem jest Butter Knife
, którego zadaniem jest wiązanie widoków do obiektów.