В программная инженерия, инверсия управления ( IoC ) - принцип программирования. IoC инвертирует поток управления по сравнению с традиционным потоком управления. В IoC специально написанные части компьютерной программы получают поток управления от общей структуры. архитектура программного обеспечения с таким дизайном инвертирует управление по сравнению с традиционным процедурным программированием : в традиционном программировании пользовательский код, который выражает цель программы вызывает в повторно используемый библиотеки для решения общих задач, но с инверсией управления именно инфраструктура вызывает пользовательский или специфичный для задачи код.
Инверсия управления используется для увеличения модульности программы и делает ее расширяемой, и имеет приложения в объектно-ориентированном программировании и других парадигмы программирования. Этот термин был использован Майклом Маттссоном в диссертации, взятой оттуда Стефано Маццокки и популяризованной им в 1999 году в несуществующем проекте Apache Software Foundation, Avalon, а затем популяризирован в 2004 году Робертом К.. Мартин и Мартин Фаулер.
Этот термин связан с принципом инверсии зависимостей, но отличается от него, который касается разделения зависимостей между высокоуровневые и низкоуровневые уровни через общие абстракции. Общая концепция также связана с программированием, управляемым событиями, поскольку оно часто реализуется с использованием IoC, так что пользовательский код обычно касается только обработки событий, тогда как цикл событий а отправка событий / сообщений обрабатывается фреймворком или средой выполнения.
В качестве примера при традиционном программировании основная функция приложения может выполнять вызовы функций в библиотеке меню для отображения списка доступных команд и запроса пользователь должен выбрать один. Таким образом, библиотека вернет выбранную опцию как значение вызова функции, и основная функция использует это значение для выполнения связанной команды. Этот стиль был распространен в текстовых интерфейсах. Например, почтовый клиент может показывать экран с командами для загрузки новой почты, ответа на текущее письмо, запуска новой почты и т. Д., И выполнение программы будет блокироваться до тех пор, пока пользователь не нажмет клавишу для выбора команда.
С другой стороны, при инверсии управления программа будет написана с использованием программной среды, которая знает общие поведенческие и графические элементы, такие как оконные системы, меню, управление мышью и т. д. Настраиваемый код «заполняет пробелы» для платформы, такой как предоставление таблицы пунктов меню и регистрация подпрограммы кода для каждого элемента, но это структура, которая отслеживает действия пользователя и вызывает подпрограмму при выборе пункта меню. В примере с почтовым клиентом фреймворк может следить за вводом как с клавиатуры, так и с помощью мыши и вызывать команду, вызванную пользователем, любым из способов, и в то же время отслеживать сетевой интерфейс, чтобы узнать, поступают ли новые сообщения. и обновлять экран при обнаружении сетевой активности. Та же самая структура может быть использована в качестве скелета для программы электронных таблиц или текстового редактора. И наоборот, фреймворк ничего не знает о веб-браузерах, электронных таблицах или текстовых редакторах; реализация их функций требует специального кода.
Инверсия управления подразумевает, что код многократного использования и код конкретной проблемы разрабатываются независимо, даже если они работают вместе в приложении. Программные среды, обратные вызовы, планировщики, циклы событий, внедрение зависимостей и шаблонный метод являются примерами шаблонов проектирования, которые следуют принципу инверсии управления, хотя этот термин чаще всего используется в контексте объектно-ориентированного программирования..
Инверсия управления служит следующей схеме цели:
Инверсия управления иногда шутливо называют «голливудским принципом» : Не звоните нам, мы вам перезвоним ».
Инверсия управления - не новый термин в информатике. Мартин Фаулер прослеживает этимологию фразы до 1988 года, но она тесно связана с концепцией программной инверсии, описанной Майклом Джексоном в его Методология структурированного программирования Джексона в 1970-х годах. восходящий синтаксический анализатор можно рассматривать как инверсию нисходящего синтаксического анализатора : в одном случае управление принадлежит синтаксическому анализатору, а в другом случае - с приложением-получателем.
Внедрение зависимости - это особый тип IoC. Локатор служб , такой как Java Naming and Directory Interface (JNDI), аналогичен. В статье Лука Бергмана это представлено как архитектурный принцип.
В статье Роберта К. Мартина принцип инверсии зависимостей и абстракция с помощью наслоения объединяются. Его причина использовать термин «инверсия» - это сравнение с традиционными методами разработки программного обеспечения. Когда он говорит об инверсии зависимостей, он описывает разъединение сервисов посредством абстракции слоев. Этот принцип используется, чтобы узнать, где находятся границы системы в дизайне уровней абстракции.
В традиционном программировании поток в бизнес-логике определяется объектами, которые статически привязаны к друг друга. При инверсии управления поток зависит от графа объектов, который строится во время выполнения программы. Такой динамический поток стал возможным благодаря взаимодействиям объектов, которые определяются через абстракции. Эта привязка времени выполнения достигается с помощью таких механизмов, как внедрение зависимостей или локатор служб. В IoC код также может быть связан статически во время компиляции, но поиск кода для выполнения путем чтения его описания из внешней конфигурации вместо прямой ссылки в самом коде.
При внедрении зависимостей зависимый объект или модуль связывается с объектом, который ему нужен во время времени выполнения. Какой конкретный объект будет удовлетворять зависимости во время выполнения программы, обычно не может быть известно на времени компиляции с помощью статического анализа. Хотя здесь описывается взаимодействие с объектами, этот принцип может применяться к другим методологиям программирования, помимо объектно-ориентированного программирования.
. Чтобы запущенная программа могла связывать объекты друг с другом, объекты должны обладать совместимыми интерфейсами.. Например, класс A
может делегировать поведение интерфейсу I
, который реализуется классом B
; программа создает экземпляры A
и B
, а затем внедряет B
в A
.
В объектно-ориентированном программировании существует несколько основных методов реализации инверсии управления. Это:
В оригинальной статье автора Мартин Фаулер, обсуждаются первые три различных метода. В описании инверсии типов управления упоминается последний. Часто контекстный поиск выполняется с помощью локатора служб
Большинство фреймворков, таких как .NET или Enterprise Java, отображают этот шаблон:
открытый класс ServerFacade {общедоступныйV responseToRequest (запрос K) {если (businessLayer.validateRequest (запрос)) {Данные данных = DAO.getData (запрос); return Aspect.convertData (данные); } return null; }}
Этот базовый план на Java дает пример кода, следующего за методологией IoC. Однако важно, чтобы в ServerFacade
было сделано много предположений о данных, возвращаемых объектом доступа к данным (DAO).
Хотя все эти предположения могут быть верными в какой-то момент, они связывают реализацию ServerFacade
с реализацией DAO. Разработка приложения способом инверсии управления полностью передаст управление объекту DAO. Тогда код станет
публичным классом ServerFacade {общедоступнымV responseToRequest (K-запрос, DAO dao) {return dao.getData (request); }}
Пример показывает, что способ создания метода responseToRequest
определяет, используется ли IoC. Это способ использования параметров, определяющих IoC. Это напоминает стиль передачи сообщений, который используют некоторые объектно-ориентированные языки программирования.