Я видел несколько рекомендованных к использованию контейнеров IoC в коде. Мотивация проста. Возьмите следующий введенный код зависимости:
class UnitUnderTest
{
std::auto_ptr<Dependency> d_;
public:
UnitUnderTest(
std::auto_ptr<Dependency> d = std::auto_ptr<Dependency>(new ConcreteDependency)
) : d_(d)
{
}
};
TEST(UnitUnderTest, Example)
{
std::auto_ptr<Dependency> dep(new MockDependency);
UnitUnderTest uut(dep);
//Test here
}
В:
class UnitUnderTest
{
std::auto_ptr<Dependency> d_;
public:
UnitUnderTest()
{
d_.reset(static_cast<Dependency *>(IocContainer::Get("Dependency")));
}
};
TEST(UnitUnderTest, Example)
{
UnitUnderTest uut;
//Test here
}
//Config for IOC container normally
<Dependency>ConcreteDependency</Dependency>
//Config for IOC container for testing
<Dependency>MockDependency</Dependency>
(Выше приведен пример гипотетического C ++)
Хотя я согласен, что это упрощает интерфейс класса, удаляя параметр конструктора зависимостей, я думаю, что лекарство хуже, чем болезнь, по нескольким причинам. Во-первых, и это очень важно для меня, это делает вашу программу зависимой от внешнего файла конфигурации. Если вам нужно одиночное двоичное развертывание, вы просто не сможете использовать эти типы контейнеров. Вторая проблема заключается в том, что API теперь слабый и худший, строго типизированный. Доказательством (в этом гипотетическом примере) является строковый аргумент контейнера IoC и приведение к результату.
Итак ... есть ли другие преимущества использования таких контейнеров или я просто не согласен с теми, кто рекомендует контейнеры?
Ответы:
В большом приложении с большим количеством слоев и множеством движущихся частей недостатки становятся менее значительными по сравнению с преимуществами.
Контейнер «упрощает интерфейс» класса, но делает это очень важным способом. Контейнер является решением проблемы, которую создает внедрение зависимостей, а именно необходимость передавать зависимости повсеместно, через графы объектов и через функциональные области. У вас есть один небольшой пример, который имеет одну зависимость - что, если у этого объекта было три зависимости, а у объектов, которые зависели от него, было несколько объектов, которые зависели от них , и так далее? Без контейнера объекты наверху этих цепочек зависимостей в конечном итоге становятся ответственными за отслеживание всех зависимостей во всем приложении.
Также есть разные виды контейнеров. Не все из них имеют строковую типизацию, и не все из них требуют конфигурационных файлов.
источник
Инфраструктура Guice IoC из Java основана не на файле конфигурации, а на коде конфигурации . Это означает, что конфигурация является кодом, не отличающимся от кода, составляющего ваше фактическое приложение, и может быть реорганизована и т. Д.
Я считаю, что Guice - это инфраструктура Java IoC, которая, наконец, правильно настроила конфигурацию
источник
Этот великий SO ответ на Бен Scheirman подробно некоторые примеры кода в C #; некоторые преимущества IoC-контейнеров (DI):
источник