Что такое инверсия контроля? - PullRequest
1618 голосов
/ 06 августа 2008

Инверсия управления (или IoC) может привести к путанице при первом обнаружении.

  1. Что это?
  2. Какую проблему это решает?
  3. Когда целесообразно использовать, а когда нет?

Ответы [ 34 ]

1313 голосов
/ 06 августа 2008

Шаблоны Inversion of Control (IoC) и Dependency Injection (DI) предназначены для удаления зависимостей из вашего кода.

Например, скажем, в вашем приложении есть компонент текстового редактора, и вы хотите обеспечить проверку орфографии. Ваш стандартный код будет выглядеть примерно так:

public class TextEditor {

    private SpellChecker checker;

    public TextEditor() {
        this.checker = new SpellChecker();
    }
}

То, что мы здесь сделали, создает зависимость между TextEditor и SpellChecker. В сценарии IoC мы бы вместо этого сделали что-то вроде этого:

public class TextEditor {

    private IocSpellChecker checker;

    public TextEditor(IocSpellChecker checker) {
        this.checker = checker;
    }
}

В первом примере кода мы создаем экземпляр SpellChecker (this.checker = new SpellChecker();), что означает, что класс TextEditor напрямую зависит от класса SpellChecker.

Во втором примере кода мы создаем абстракцию, имея класс зависимостей SpellChecker в сигнатуре конструктора TextEditor (без инициализации зависимости в классе). Это позволяет нам вызвать зависимость и затем передать ее классу TextEditor следующим образом:

SpellChecker sc = new SpellChecker; // dependency
TextEditor textEditor = new TextEditor(sc);

Теперь клиент, создающий класс TextEditor, имеет контроль над тем, какую реализацию SpellChecker использовать, потому что мы внедряем зависимость от подписи TextEditor.

Это простой пример, хорошая серия статей Симона Бусоли, которая объясняет это более подробно.

549 голосов
/ 06 августа 2008

Инверсия управления - это то, что вы получаете, когда ваши программные обратные вызовы, например, как программа с графическим интерфейсом.

Например, в меню старой школы у вас может быть:

print "enter your name"
read name
print "enter your address"
read address
etc...
store in database

тем самым управляя потоком взаимодействия с пользователем.

В программе с графическим интерфейсом или что-то подобное, вместо этого мы говорим:

when the user types in field a, store it in NAME
when the user types in field b, store it in ADDRESS
when the user clicks the save button, call StoreInDatabase

Так что теперь управление инвертировано ... вместо того, чтобы компьютер принимал ввод пользователя в фиксированном порядке, пользователь контролирует порядок, в котором вводятся данные, и когда данные сохраняются в базе данных.

По сути, что угодно с циклом событий, обратными вызовами или триггерами выполнения попадает в эту категорию.

388 голосов
/ 22 июля 2010

Что такое инверсия контроля?

Если вы выполните эти два простых шага, вы сделали инверсию управления:

  1. Отделить какую -задачу от , когда -то-часть.
  2. Убедитесь, что , когда деталь знает как маленький , насколько это возможно, о what part; и наоборот.

Для каждого из этих шагов возможны несколько методов, основанных на технологии / языке, которые вы используете для своей реализации.

-

Инверсия *1026* часть Inversion of Control (IoC) - запутанная вещь; потому что инверсия является относительным термином. Лучший способ понять IoC - забыть об этом слове!

-

Примеры

  • Обработка событий. Обработчики событий (часть с заданиями) - Создание событий (часть с заданиями)
  • Интерфейсы. Компонентный клиент (часть с заданиями) - реализация интерфейса компонентов (часть с заданиями)
  • xUnit fixture. Setup и TearDown (часть «что делать») - платформы xUnit вызывают программу установки в начале и TearDown в конце (часть «когда нужно делать»)
  • Шаблонный метод проектирования шаблона. часть шаблона, когда нужно делать - часть реализации простого подкласса, что нужно делать
  • Методы контейнера DLL в COM. DllMain, DllCanUnload и т. Д. (Часть «что делать») - COM / OS (часть «когда делать»)
132 голосов
/ 25 сентября 2013

Инверсия элементов управления - это разделение проблем.

Без IoC : у вас есть ноутбук компьютер и вы случайно разбили экран. И, черт возьми, вы найдете такую ​​же модель экрана ноутбука нигде на рынке. Итак, вы застряли.

с IoC : у вас есть настольный компьютер и вы случайно разбили экран. Вы обнаружите, что можете просто взять практически любой настольный монитор с рынка, и он хорошо работает с вашим рабочим столом.

В этом случае ваш рабочий стол успешно поддерживает IoC. Он принимает различные типы мониторов, а ноутбук - нет, для его устранения требуется специальный экран.

92 голосов
/ 04 марта 2013

Инверсия контроля (или IoC) - это примерно получение свободы (Вы женаты, вы потеряли свободу и вас контролируют. Вы развелись, вы только что внедрили инверсию контроля. называется "развязан". Хорошая компьютерная система препятствует очень тесным отношениям.) больше гибкости (кухня в вашем офисе подает только чистую водопроводную воду, это ваш единственный выбор, когда вы хотите пить. Инверсия контроля путем настройки новой кофемашины. Теперь вы можете гибко выбирать водопроводную воду или кофе.) И меньше зависимости (у вашего партнера есть работа, у вас нет работы, вы финансово зависит от вашего партнера, поэтому вы находитесь под контролем. Вы нашли работу, вы внедрили Inversion of Control. Хорошая компьютерная система поощряет независимость.)

Когда вы используете настольный компьютер, у вас есть подчиненный (или, скажем, управляемый). Вы должны сидеть перед экраном и смотреть на него. Использование клавиатуры для ввода текста и использование мыши для навигации. И плохо написанное программное обеспечение может поработить вас еще больше. Если вы замените свой рабочий стол на ноутбук, то у вас несколько перевернутый контроль. Вы можете легко взять его и передвигаться. Так что теперь вы можете контролировать, где вы находитесь с вашим компьютером, а не компьютер, управляющий им.

Реализуя Inversion of Control, потребитель программного / объектного объекта получает больше элементов управления / опций над программным обеспечением / объектами, вместо того, чтобы управлять им или иметь меньше опций.

Имея в виду вышеупомянутые идеи. Мы все еще скучаем по ключевой части IoC. В сценарии IoC потребитель программного обеспечения / объектов представляет собой сложную структуру. Это означает, что созданный вами код не вызывается вами. Теперь давайте объясним, почему этот способ работает лучше для веб-приложения.

Предположим, ваш код - это группа работников. Им нужно построить машину. Этим работникам нужно место и инструменты (программная структура) для сборки автомобиля. Традиционная программная структура будет похожа на гараж со многими инструментами. Поэтому рабочие должны сами составить план и использовать инструменты для сборки автомобиля. Создание автомобиля - дело непростое, рабочим будет очень сложно правильно планировать и сотрудничать. Программная платформа modern будет похожа на современный автомобильный завод со всеми необходимыми средствами и менеджерами. Рабочим не нужно составлять никакого плана, менеджеры (часть структуры, они самые умные люди и разработали самый сложный план) помогут координировать действия, чтобы работники знали, когда выполнять свою работу (среда называет ваш код). Рабочие просто должны быть достаточно гибкими, чтобы использовать любые инструменты, которые им дают менеджеры (используя Dependency Injection).

Хотя рабочие дают контроль над управлением проектом на верхнем уровне менеджерам (каркас). Но хорошо, что некоторые профессионалы помогают. Это концепция IoC действительно происходит от.

Современные веб-приложения с архитектурой MVC зависят от инфраструктуры, выполняющей маршрутизацию URL-адресов, и устанавливают контроллеры для вызова платформы.

Внедрение зависимостей и инверсия управления связаны между собой. Внедрение зависимостей находится на уровне микро , а инверсия управления - на уровне макро . Вы должны съесть каждый укус (внедрить DI), чтобы закончить прием пищи (внедрить IoC).

82 голосов
/ 12 февраля 2010

Перед использованием Inversion of Control вы должны хорошо знать, что у него есть свои плюсы и минусы, и вы должны знать, почему вы используете его, если вы это делаете.

Плюсы:

  • Ваш код отделен, чтобы вы могли легко обмениваться реализациями интерфейса с альтернативными реализациями
  • Это сильный мотиватор для кодирования против интерфейсов вместо реализаций
  • Очень легко написать модульные тесты для вашего кода, потому что он не зависит ни от чего, кроме объектов, которые он принимает в своих конструкторах / установщиках, и вы можете легко инициализировать их с нужными изолированными объектами.

Минусы:

  • IoC не только инвертирует поток управления в вашей программе, но и значительно затуманивает его. Это означает, что вы больше не можете просто читать свой код и переходить из одного места в другое, потому что соединения, которые обычно были бы в вашем коде, больше не находятся в коде. Вместо этого он интерпретируется в метаданных в файлах конфигурации или аннотациях XML и в коде вашего контейнера IoC.
  • Возникает новый класс ошибок, в которых вы неправильно указали свою конфигурацию XML или свои аннотации, и вы можете потратить много времени на выяснение того, почему ваш контейнер IoC вводит нулевую ссылку в один из ваших объектов при определенных условиях.

Лично я вижу сильные стороны IoC, и они мне действительно нравятся, но я стараюсь избегать IoC, когда это возможно, потому что он превращает ваше программное обеспечение в набор классов, которые больше не представляют собой «настоящую» программу, а просто то, что нужно объединяются с помощью конфигурации XML или метаданных аннотации и разваливаются (и распадаются) без них.

62 голосов
/ 06 августа 2008
  1. Статья в Википедии . Для меня инверсия контроля превращает ваш последовательно написанный код и превращает его в структуру делегирования. Вместо того, чтобы ваша программа явно контролировала все, ваша программа настраивает класс или библиотеку с определенными функциями, которые будут вызываться, когда происходят определенные вещи.

  2. Устраняет дублирование кода. Например, в старые времена вы вручную писали свой собственный цикл событий, опрашивая системные библиотеки на предмет новых событий. В настоящее время большинство современных API-интерфейсов просто сообщают системным библиотекам, какие события вас интересуют, и сообщают, когда они происходят.

  3. Инверсия управления - это практичный способ уменьшить дублирование кода, и если вы обнаружите, что копируете весь метод и изменяете только небольшой фрагмент кода, вы можете рассмотреть его с инверсией управления. Инверсия управления упрощается во многих языках благодаря концепции делегатов, интерфейсов или даже необработанных указателей на функции.

    Это не подходит для использования во всех случаях, потому что поток программы может быть сложнее следовать при написании таким образом. Это полезный способ разработки методов при написании библиотеки, которая будет использоваться повторно, но ее следует использовать с осторожностью в ядре вашей собственной программы, если это действительно не решает проблему дублирования кода.

42 голосов
/ 07 августа 2008

Но я думаю, что вы должны быть очень осторожны с этим. Если вы будете злоупотреблять этим шаблоном, вы создадите очень сложный дизайн и еще более сложный код.

Как в этом примере с TextEditor: если у вас есть только один SpellChecker, может быть, нет необходимости использовать IoC? Если вам не нужно писать модульные тесты или что-то ...

В любом случае: будь разумным. Шаблон дизайна - это хорошая практика , но не Библия, которую нужно проповедовать. Не вставляйте его везде.

40 голосов
/ 25 сентября 2013

Предположим, вы объект. И вы идете в ресторан:

Без IoC : вы спрашиваете «яблоко», и вам всегда подают яблоко, когда вы спрашиваете больше.

С IoC : Вы можете попросить "фрукты". Вы можете получать разные фрукты каждый раз, когда вас обслуживают. например, яблоко, апельсин или арбуз.

Итак, очевидно, что IoC предпочтительнее, когда вам нравятся сорта.

37 голосов
/ 19 сентября 2008

IoC / DI для меня выталкивает зависимости к вызывающим объектам. Супер просто.

Нетехичный ответ - возможность поменять двигатель в машине прямо перед его включением. Если все правильно подключено (интерфейс), вы хороши.

...