Constructor Injection ma tę zaletę, że wyraźnie określa zależność i zmusza klienta do zapewnienia wystąpienia. Może także zagwarantować, że klient nie będzie mógł później zmienić instancji. Jednym (możliwym) minusem jest to, że musisz dodać parametr do swojego konstruktora.
Zaletą Setter Injection jest to, że nie wymaga dodawania parametru do konstruktora. Nie wymaga również od klienta ustawienia instancji. Jest to przydatne w przypadku zależności opcjonalnych. Może to być również przydatne, jeśli chcesz, aby klasa utworzyła domyślnie np. Prawdziwe repozytorium danych, a następnie w teście możesz użyć setera do zastąpienia go instancją testową.
Interfejs Iniekcji , o ile wiem, nie różni się niczym od wtrysku setera. W obu przypadkach (opcjonalnie) ustawia się zależność, którą można zmienić później.
Ostatecznie jest to kwestia preferencji i tego, czy wymagana jest zależność, czy nie . Osobiście używam zastrzyku konstruktora prawie wyłącznie. Podoba mi się, że wyraźnie określa zależności klasy, zmuszając klienta do zapewnienia wystąpienia w konstruktorze. Podoba mi się również to, że klient nie może zmienić instancji po fakcie.
Często moim jedynym powodem przekazania dwóch osobnych implementacji jest testowanie. W produkcji mogę zdać DataRepository
, ale w testach zdałbym FakeDataRepository
. W takim przypadku zwykle dostarczam dwa konstruktory: jeden bez parametrów, a drugi akceptujący IDataRepository
. Następnie w konstruktorze bez parametrów wywołam połączenie z drugim konstruktorem i przekażę komendę new DataRepository()
.
Oto przykład w języku C #:
public class Foo
{
private readonly IDataRepository dataRepository;
public Foo() : this(new DataRepository())
{
}
public Foo(IDataRespository dataRepository)
{
this.dataRepository = dataRepository;
}
}
Jest to znane jako zastrzyk uzależnienia od ubogich. Podoba mi się, ponieważ w kodzie klienta produkcyjnego nie muszę się powtarzać, mając kilka powtarzających się instrukcji, które wyglądają
var foo = new Foo(new DataRepository());
Nadal jednak mogę przekazać alternatywną implementację do testowania. Zdaję sobie sprawę, że w DI Poor Man zapisuję na stałe swoją zależność, ale jest to dla mnie do zaakceptowania, ponieważ do testów używam głównie DI.