Кажется, существует большая путаница в отношении схемы инверсии контроля (IoC). Многие люди приравнивают его к шаблону стратегии или компонентной модели, но это сравнение на самом деле не отражает то, что представляет собой IoC. IoC действительно о том, как получается зависимость. Позволь мне привести пример:
class Game {
void Load() {
this.Sprite.Load(); // loads resource for drawing later
}
}
class Sprite {
void Load() {
FileReader reader = new FileReader("path/to/resource.gif");
// load image from file
}
}
Из приведенного выше ясно, что Sprite.Load
зависит от FileReader
. Когда вы хотите проверить метод, вам нужно следующее:
- Файловая система на месте
- Тестовый файл для загрузки из файловой системы
- Возможность вызвать общие ошибки файловой системы
Первые два очевидны, но если вы хотите убедиться, что ваша обработка ошибок работает так, как ожидалось, вам действительно нужен №3. В обоих случаях вы потенциально немного замедлили свои тесты, поскольку теперь им нужно перейти на диск, и вы, вероятно, сделали вашу среду тестирования более сложной.
Цель IoC состоит в том, чтобы отделить использование поведения от его конструкции. Обратите внимание, как это отличается от шаблона стратегии. С помощью шаблона «Стратегия» цель состоит в том, чтобы инкапсулировать многократно используемый фрагмент поведения, чтобы вы могли легко расширить его в будущем; ему нечего сказать о том, как строятся стратегии.
Если бы мы переписали Sprite.Load
описанный выше метод, мы бы, скорее всего, получили :
class Sprite {
void Load(IReader reader) {
// load image through reader
}
}
Теперь мы отделили конструкцию читателя от ее использования. Таким образом, во время тестирования можно поменять тест-ридер. Это означает, что ваша среда тестирования больше не нуждается в файловой системе, тестовых файлах и может легко моделировать события ошибок.
Обратите внимание, что я переписал две вещи. Я создал интерфейс, IReader
который инкапсулировал некоторое поведение - то есть реализовал шаблон Стратегии. Кроме того, я перенес ответственность за создание правильного читателя в другой класс.
Может быть, нам не нужно новое имя шаблона для описания выше. Это выглядит как сочетание шаблонов Strategy и Factory (для контейнеров IoC). При этом я не уверен, на каком основании люди возражают против этого шаблона, поскольку ясно, что он решает реальную проблему, и, конечно, для меня не очевидно, как это связано с Java.