Iniezione costruttore ha il vantaggio di rendere esplicita la dipendenza e obbliga il client a fornire un'istanza. Può inoltre garantire che il client non possa modificare l'istanza in un secondo momento. Uno (possibile) svantaggio è che devi aggiungere un parametro al tuo costruttore.
Iniezione settetta ha il vantaggio che non richiede l'aggiunta di un parametro al costruttore. Inoltre, non richiede che il client imposti l'istanza. Questo è utile per dipendenze opzionali. Ciò può anche essere utile se si desidera che la classe crei, ad esempio, un vero repository di dati per impostazione predefinita, quindi in un test è possibile utilizzare il setter per sostituirlo con un'istanza di test.
Injection Interface , per quanto posso dire, non è molto diverso dall'iniezione di setter. In entrambi i casi, puoi (facoltativamente) impostare una dipendenza che può essere modificata in seguito.
In definitiva si tratta di preferenza e se una dipendenza è richiesta o meno. Personalmente, uso l'iniezione del costruttore quasi esclusivamente. Mi piace il fatto che rende esplicite le dipendenze di una classe forzando il client a fornire un'istanza nel costruttore. Mi piace anche che il client non possa modificare l'istanza dopo il fatto.
Spesso, il mio unico motivo per passare in due implementazioni separate è il test. In produzione, posso passare in DataRepository
, ma in fase di test, vorrei passare a FakeDataRepository
. In questo caso fornirò solitamente due costruttori: uno senza parametri e un altro che accetta IDataRepository
. Quindi, nel costruttore senza parametri, concateneremo una chiamata al secondo costruttore e inoltrerò un new DataRepository()
.
Ecco un esempio in C #:
public class Foo
{
private readonly IDataRepository dataRepository;
public Foo() : this(new DataRepository())
{
}
public Foo(IDataRespository dataRepository)
{
this.dataRepository = dataRepository;
}
}
Questo è noto come Iniezione delle dipendenze di Poor Man. Mi piace perché nel codice client di produzione, non ho bisogno di ripetermi avendo diverse dichiarazioni ripetute che assomigliano a
var foo = new Foo(new DataRepository());
Tuttavia, posso ancora passare in un'implementazione alternativa per il test. Mi rendo conto che con DI di Poor Man sto codificando la mia dipendenza, ma questo è accettabile per me dal momento che utilizzo principalmente DI per i test.