Преимущество Constructor Injection заключается в том, что оно делает зависимость явной и вынуждает клиента предоставлять экземпляр. Это также может гарантировать, что клиент не сможет изменить экземпляр позже. Одним (возможным) недостатком является то, что вам нужно добавить параметр в ваш конструктор.
Преимущество Setter Injection заключается в том, что он не требует добавления параметра в конструктор. Это также не требует, чтобы клиент установил экземпляр. Это полезно для необязательных зависимостей. Это также может быть полезно, если вы хотите, чтобы класс создавал, например, реальное хранилище данных по умолчанию, а затем в тесте вы можете использовать установщик, чтобы заменить его экземпляром тестирования.
Интерфейсная инъекция , насколько я могу судить, не сильно отличается от настройки инъекции. В обоих случаях вы (необязательно) устанавливаете зависимость, которую можно изменить позже.
В конечном счете, это вопрос предпочтения и того, требуется ли зависимость . Лично я использую конструктор инъекций почти исключительно. Мне нравится, что он делает зависимости класса явными, заставляя клиента предоставлять экземпляр в конструкторе. Мне также нравится, что клиент не может изменить экземпляр после факта.
Часто моя единственная причина перехода на две отдельные реализации - это тестирование. В производстве я могу перейти в a DataRepository
, но в тестировании я бы прошел в FakeDataRepository
. В этом случае я обычно предоставляю два конструктора: один без параметров, а другой принимает a IDataRepository
. Затем в конструкторе без параметров я буду связывать вызов второго конструктора и передавать в new DataRepository()
.
Вот пример в C #:
public class Foo
{
private readonly IDataRepository dataRepository;
public Foo() : this(new DataRepository())
{
}
public Foo(IDataRespository dataRepository)
{
this.dataRepository = dataRepository;
}
}
Это известно как инъекция зависимости бедного человека. Мне это нравится, потому что в производственном клиентском коде мне не нужно повторяться, имея несколько повторяющихся утверждений, которые выглядят как
var foo = new Foo(new DataRepository());
Тем не менее, я все еще могу передать альтернативную реализацию для тестирования. Я понимаю, что с DI Бедного Человека я жестко программирую свою зависимость, но это приемлемо для меня, так как я в основном использую DI для тестирования