Я согласен, что доведенный до крайности, DI может нарушать инкапсуляцию. Обычно DI раскрывает зависимости, которые никогда не были действительно инкапсулированы. Вот упрощенный пример, заимствованный у Мишко Хевери Синглтоны - это патологические лжецы :
Вы начинаете с теста CreditCard и пишете простой модульный тест.
@Test
public void creditCard_Charge()
{
CreditCard c = new CreditCard("1234 5678 9012 3456", 5, 2008);
c.charge(100);
}
В следующем месяце вы получите счет на 100 долларов. Почему вы получили заряд? Юнит-тест затронул производственную базу данных. Внутренне, CreditCard звонит Database.getInstance()
. Рефакторинг CreditCard таким образом, чтобы в его конструкторе заняло DatabaseInterface
, показывает факт наличия зависимости. Но я бы сказал, что для начала зависимость никогда не заключалась в капсулу, поскольку класс CreditCard вызывает внешне видимые побочные эффекты. Если вы хотите протестировать CreditCard без рефакторинга, вы, безусловно, можете наблюдать зависимость.
@Before
public void setUp()
{
Database.setInstance(new MockDatabase());
}
@After
public void tearDown()
{
Database.resetInstance();
}
Я не думаю, что стоит беспокоиться о том, уменьшает ли представление базы данных как зависимость инкапсуляцию, потому что это хороший дизайн. Не все решения DI будут такими простыми. Однако ни один из других ответов не показывает встречный пример.