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

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

  1. Что это?
  2. Какую проблему это решает?
  3. Когда это целесообразно использовать, а когда нет?
6.08.2008 03:35:27
Проблема большинства этих ответов заключается в используемой терминологии. Что такое контейнер? Инверсия? Зависимость? Объясните это в терминах обывателя без громких слов
kirk.burleson 16.09.2010 01:30:15
Смотрите также на Programmers.SE: Почему Inversion of Control назван так?
Izkata 22.07.2013 20:34:07
Это инъекция зависимостей (DI) - см. Описание Мартина Фаулера здесь: martinfowler.com/articles/injection.html#InversionOfControl
Ricardo Sanchez 16.09.2014 23:16:22
Это прилагательное, а не существительное, это не вещь, это описание изменения, внесенного в код, где управление потоком находится в делегате, а не в контейнере.
Martin Spamer 12.08.2016 13:21:00
30 ОТВЕТОВ
РЕШЕНИЕ

Шаблоны 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;
    }
}

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

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

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

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

1493
25.11.2019 10:27:18
Хороший наглядный пример. Однако предположим, что вместо того, чтобы требовать передачи интерфейса ISpellChecker в конструктор объекта, мы представили его как настраиваемое свойство (или метод SetSpellChecker). Будет ли это все еще представлять собой IoC?
devios1 20.12.2008 02:36:12
chainguy1337 - да, будет. Использование таких сеттеров называется инъекцией сеттера, а не инжектором конструктора (оба метода внедрения зависимостей). IoC - это довольно общий шаблон, но инъекция зависимостей достигает IoC
Jack Ukleja 29.08.2009 01:25:47
Несмотря на множество голосов, этот ответ неверен. Пожалуйста, смотрите martinfowler.com/articles/injection.html#InversionOfControl . В частности, обратите внимание на часть, в которой говорится: «Инверсия контроля - это слишком общий термин, и поэтому люди находят его непонятным. В результате большого обсуждения с различными сторонниками IoC мы остановились на названии Dependency Injection».
Rogério 2.04.2010 14:10:30
Я согласен с @Rogeria. это не объясняет, почему он называется IoC, и я удивлен количеством голосов «за» ;-)
Aravind Yarram 23.12.2010 20:01:16
Я на стороне @Rogerio и @Pangea. Это может быть хорошим примером для внедрения в конструктор, но не хорошим ответом на исходный вопрос. IoC, как определено Фаулером , может быть реализован без использования какого-либо внедрения, например, с помощью локатора службы или даже простого наследования.
mtsz 14.07.2011 00:49:47
  1. Статья в Википедии . Для меня инверсия контроля превращает ваш последовательно написанный код и превращает его в структуру делегирования. Вместо того, чтобы ваша программа явно контролировала все, ваша программа устанавливает класс или библиотеку с определенными функциями, которые будут вызываться, когда происходят определенные вещи.

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

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

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

67
6.08.2008 04:33:19
Я нахожу эту статью в Википедии очень запутанной и нуждающейся в исправлении. Проверьте страницу обсуждения для смеха.
devios1 20.12.2008 02:34:40
Написание собственного цикла обработки событий все еще может быть инверсией управления, если этот цикл обработки событий занимает место фреймворка, а остальная часть кода использует принцип IoC, вы только что написали свою собственную фреймворк. Это на самом деле неплохая вещь, она повышает читабельность за счет лишь немного большего кодирования (не то чтобы это всегда было уместно).
lijat 28.08.2018 06:34:57

Я согласен с NilObject , но я хотел бы добавить к этому:

если вы копируете весь метод и изменяете только небольшой фрагмент кода, вы можете рассмотреть его с инверсией управления

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

17
23.05.2017 11:47:31

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

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

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

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

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

632
9.05.2019 00:33:03
не помечайте этого парня. технически он прав. martinfowler.com/bliki/InversionOfControl.html IoC является очень общим принципом. Поток управления «инвертируется» путем внедрения зависимостей, потому что вы фактически делегировали зависимости некоторой внешней системе (например, контейнеру IoC)
Jack Ukleja 29.08.2009 01:51:48
Согласился с комментарием Шнайдера. 5 понижений? Разум поражает, так как это единственный правильный ответ. Обратите внимание на открытие: « как в графической программе». Внедрение зависимостей является лишь наиболее распространенной реализацией IoC.
Jeff Sternal 12.02.2010 14:45:37
Действительно, это один из немногих правильных ответов! Ребята, IoC не принципиально о зависимостях. Не за что.
Rogério 2.04.2010 14:08:22
+1 - это хорошее описание (с примером) следующего высказывания Мартина Фаулера: «Ранние пользовательские интерфейсы контролировались прикладной программой. У вас была бы последовательность команд, таких как« Введите имя »,« введите адрес »; Программа будет выдавать приглашения и получать ответы на каждый из них. С графическими (или даже на основе экрана) пользовательскими интерфейсами структура пользовательского интерфейса будет содержать этот основной цикл, а ваша программа вместо этого будет предоставлять обработчики событий для различных полей на экране. программа была перевернута, отодвинута от вас в рамки ".
Ashish Gupta 16.10.2010 08:29:36
Теперь я понимаю, почему его иногда злобно называют «принципом Голливуда: не звоните нам, мы вам позвоним»
Alexander Suraphel 6.11.2013 07:27:46

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

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

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

45
6.08.2008 22:08:27
Откуда ты знаешь, что у тебя будет только одна проверка орфографии?
Trace 14.01.2017 08:04:54
@Trace Вы можете знать, как программа, которую вы собираетесь написать, например, будет использоваться. Тем не менее, некоторые методы, такие как внедрение зависимостей, настолько дешевы, что редко есть причина не использовать их в подобном случае.
lijat 28.08.2018 06:36:21
  1. Инверсия управления - это шаблон, используемый для разделения компонентов и слоев в системе. Шаблон реализуется путем внедрения зависимостей в компонент при его создании. Эти зависимости обычно предоставляются в качестве интерфейсов для дальнейшей развязки и поддержки тестируемости. Контейнеры IoC / DI, такие как Castle Windsor, Unity - это инструменты (библиотеки), которые можно использовать для обеспечения IoC. Эти инструменты предоставляют расширенные функции помимо простого управления зависимостями, включая время жизни, AOP / перехват, политику и т. Д.

  2. а. Освобождает компонент от ответственности за управление его зависимостями.
    б. Предоставляет возможность менять реализации зависимостей в разных средах.
    с. Позволяет компоненту быть протестированным путем проверки зависимостей.
    д. Предоставляет механизм для совместного использования ресурсов в приложении.

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

26
23.08.2013 12:03:17
На самом деле IoC в основном не занимается управлением зависимостями. Пожалуйста, посетите martinfowler.com/articles/injection.html#InversionOfControl. В частности, обратите внимание на часть, в которой говорится: «Инверсия контроля - слишком общий термин, и поэтому люди находят его непонятным. В результате мы много обсуждаем с различными сторонниками IoC. остановился на названии «Инъекция зависимости».
Rogério 2.04.2010 14:12:59

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

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

43
19.09.2008 02:54:35
  1. Итак, номер 1 выше . Что такое инверсия контроля?

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

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

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

public class MessagePublisher<RECORD,MESSAGE>
{
    public MessagePublisher(IMapper<RECORD,MESSAGE> mapper,IRemoteEndpoint endPointToSendTo)
    {
      //setup
    }
}

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

О да, есть проблемы с тестируемостью, но они вторичны по отношению к преимуществам IoC / DI.

Я определенно люблю IoC / DI.

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

3
23.05.2017 12:10:45
ferventcoder 2.01.2009 19:12:52

Например, задача № 1 - создать объект. Без концепции IOC задача №1 должна выполняться программистом. Но с концепцией IOC задача №1 будет выполняться контейнером.

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

Я нашел один хороший пример здесь .

17
27.01.2010 12:47:07
Контейнер - это концепция в IoC, где объектная модель, включая зависимости (отношения между объектом «пользователь» и «используемым» объектом) и экземплярами объекта, находится и управляется - например, содержится. Контейнер обычно предоставляется средой IoC, такой как Spring. Думайте об этом как о хранилище времени выполнения для объектов, которые составляют ваше приложение.
The Awnry Bear 29.06.2012 19:05:50

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

Плюсы:

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

Минусы:

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

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

91
8.08.2016 18:06:24
Первый обман неверен. В идеале в вашем коде должен использоваться только один контейнер IOC, и это ваш основной метод. Все остальное должно идти вниз оттуда
mwjackson 28.10.2010 15:23:08
Я думаю, что он имеет в виду, вы не можете просто прочитать: myService.DoSomething () и перейти к определению DoSomething, потому что в IoC myService - это просто интерфейс, а фактическая реализация вам неизвестна, если вы не посмотрите это в конфигурационных файлах xml или в основном методе, где ваш ioc настраивается.
chrismay 23.05.2011 22:59:11
Вот где Resharper помогает - «нажми перейти к реализации» в интерфейсе. Отказ от IoC (или, точнее, DI из вашего примера), вероятно, также означает, что вы не тестируете должным образом
IThasTheAnswer 8.11.2011 04:11:27
Re: он превращает ваше программное обеспечение в набор классов, которые больше не представляют собой «настоящую» программу, а представляют собой нечто, что необходимо объединить с помощью конфигурации XML или метаданных аннотации и развалиться (и развалиться) без него - я думаю, это очень вводит в заблуждение. То же самое можно сказать о любой программе, написанной поверх фреймворка. Разница с хорошим контейнером IoC заключается в том, что вы должны иметь возможность, если ваша программа хорошо спроектирована и написана, вынуть ее и добавить другую с минимальными изменениями в коде, или вообще отказаться от IoC и сконструировать объекты вручную. ,
The Awnry Bear 29.06.2012 18:58:52
Приятно видеть реальный ответ, как этот! Я думаю, что есть много опытных программистов, знакомых с объектно-ориентированным проектированием и практикой TDD, уже использующих интерфейсы, фабричные шаблоны, модели, управляемые событиями, и имитацию, где это имеет смысл, до того как было изобретено умное слово «IoC». К сожалению, слишком много разработчиков / «архитекторов» заявляют о плохой практике, если вы не используете их предпочтительные фреймворки. Я предпочитаю лучший дизайн, использование встроенных языковых концепций и инструментов, чтобы достичь той же цели с небольшой долей сложности, т.е. без «затуманивания» реализации, как вы говорите :-)
Tony Wall 8.07.2015 14:40:34

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

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

  1. Отделите часть « что делать» от части « когда делать».
  2. Убедитесь в том, что , когда часть знает , как Литтл , как можно о какой части; наоборот.

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

-

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

-

Примеры

  • Обработка событий. Обработчики событий (часть с заданиями) - Создание событий (часть с заданиями)
  • Интерфейсы. Компонентный клиент (часть с заданиями) - реализация интерфейса компонентов (часть с заданиями)
  • xUnit крепеж. Setup и TearDown (часть «что делать») - платформы xUnit вызывают программу установки в начале и TearDown в конце (часть «когда нужно делать»)
  • Шаблон метода проектирования шаблона. часть шаблона метода when-to-do - примитивная часть реализации подкласса
  • Методы контейнера DLL в COM. DllMain, DllCanUnload и т. Д. (Часть «что делать») - COM / OS (часть «когда делать»)
416
9.05.2019 00:28:48
Как вы говорите, интерфейсы. Компонент клиент (часть «когда делать») как «когда» не имеет смысла, когда мы используем интерфейсы (например: внедрение зависимостей), мы просто абстрагируем его и даем клиенту гибкость при добавлении любой реализации, но «когда» нет участвует там. Я согласен с «когда» в случае возникновения событий обработки событий.
OldSchool 4.05.2017 15:20:15
Под компонентным клиентом я подразумевал пользователя / клиента интерфейса. Клиент знает «когда» для запуска части «что делать», является ли намерение расширить функциональность или нет.
rpattabi 5.05.2017 10:43:01
Взгляните на эту замечательную статью Мартина Фаулера. Он показывает, как интерфейсы составляют фундаментальную часть инверсии управления: martinfowler.com/articles/injection.html#InversionOfControl
rpattabi 5.05.2017 10:44:37
два первых предложения блестящие. здорово !! идеальное разделение: когда делать и что делать !! я не знаю, почему другие ответы получают так много голосов. они просто говорят коды без какого-либо понимания.
Amir Ziarati 5.06.2018 18:41:20
Мне нравится объяснение what-to-doиwhen-to-do
KimchiMan 2.12.2018 04:17:09

Кажется, что самая запутанная вещь в «IoC» - это аббревиатура и название, за которым оно стоит, - это слишком гламурное имя - почти шумное имя.

Действительно ли нам нужно имя, чтобы описать разницу между процедурным и управляемым событиями программированием? Хорошо, если нам нужно, но нужно ли нам выбирать новое имя «больше, чем жизнь», которое смущает больше, чем решает?

16
19.01.2011 03:50:19
IoC! = Управляемый событиями. Сходства (а в некоторых случаях частично совпадают), но они принципиально не являются одной и той же парадигмой.
The Awnry Bear 29.06.2012 19:04:27
Хороший вопрос. Событийное программирование - это, безусловно, IoC. Мы пишем обработчики событий, и они вызываются из цикла событий. Но IoC является более общей концепцией, чем программирование, управляемое событиями. Если вы переопределяете метод в подклассе, это также своего рода IoC. Вы пишете код, который будет вызываться при использовании соответствующей ссылки (экземпляра).
vi.su. 29.07.2014 14:48:39

Позвольте сказать, что мы делаем некоторые встречи в каком-то отеле.

Много людей, много графинов с водой, много пластиковых стаканчиков.

Когда кто-то хочет пить, она наполняет чашку, пьет и бросает чашку на пол.

Через час или около того у нас пол покрыт пластиковыми стаканчиками и водой.

Пусть инвертирует контроль.

Та же встреча в том же месте, но вместо пластиковых стаканчиков у нас есть официант с одной стеклянной чашкой (синглтон)

и она все время предлагает гостям выпить.

Когда кто-то хочет выпить, она достает из официанта стакан, пьет и возвращает его обратно официанту.

Оставляя в стороне вопрос о гигиеничности, последняя форма контроля питьевого процесса гораздо более эффективна и экономична.

И это именно то, что делает Spring (другой контейнер IoC, например: Guice). Вместо того, чтобы позволить приложению создавать то, что ему нужно, используя новое ключевое слово (с пластиковой чашкой), контейнер Spring IoC все время предлагает приложению один и тот же экземпляр (singleton) нужного объекта (стакан воды).

Думайте о себе как об организаторе такой встречи. Вам нужен способ сообщить администрации отеля, что

участникам собрания понадобится стакан воды, но не кусок пирога.

Пример:-

public class MeetingMember {

    private GlassOfWater glassOfWater;

    ...

    public void setGlassOfWater(GlassOfWater glassOfWater){
        this.glassOfWater = glassOfWater;
    }
    //your glassOfWater object initialized and ready to use...
    //spring IoC  called setGlassOfWater method itself in order to
    //offer to meetingMember glassOfWater instance

}

Полезные ссылки:-

17
26.09.2012 17:54:41
не являются объектами статического типа синглетонов?
Gokigooooks 21.11.2015 14:35:29

Очень простое письменное объяснение можно найти здесь

http://binstock.blogspot.in/2008/01/excellent-explanation-of-dependency.html

Это говорит -

«Любое нетривиальное приложение состоит из двух или более классов, которые взаимодействуют друг с другом для выполнения некоторой бизнес-логики. Традиционно каждый объект отвечает за получение своих собственных ссылок на объекты, с которыми он взаимодействует (его зависимости). При применении DI объекты получают свои зависимости во время создания некоторой внешней сущностью, которая координирует каждый объект в системе. Другими словами, зависимости вводятся в объекты ".

12
8.01.2019 20:08:37

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

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

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

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

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

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

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

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

113
6.12.2019 20:53:40
Я проголосовал за сравнение DI для брака и IoC для развода.
Marek Bar 27.04.2017 19:09:30
«Хотя работники дают контроль над управлением проектом на высшем уровне менеджерам (каркасу). Но хорошо, что некоторые профессионалы помогают. Это концепция IoC, которая действительно исходит». - Во-первых, контроль с менеджером. Можете ли вы объяснить, как этот контроль инвертируется? С помощью профессионалов (что за профессионал)? Как ?
Istiaque Ahmed 25.01.2019 16:40:49
@Istiaque Ahmed, по сравнению с гаражом, где работники полностью контролируют все, менеджеры на современном автомобильном заводе контролируют производство. Так что теперь рабочие контролируются, а не контролируются. Имейте в виду, менеджеры в этом контексте являются частью современного автомобильного завода, а не частью рабочих. Профессионалы - это менеджеры, которые профессионально планируют и производят автомобили.
Luo Jiong Hui 25.01.2019 19:15:44
Послание женатым людям: не разводитесь сейчас, в классах вашего ребенка также может быть установлен IoC.
Julian 28.01.2019 09:02:38
Да, это только мое видение брака, также IoC
balron 27.05.2019 15:14:56

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

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

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

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

44
27.07.2016 19:38:26

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

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

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

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

161
20.01.2017 13:42:11
@Luo Jiong Hui Хорошее объяснение.
Sachin 26.10.2017 06:32:35
Большинство шаблонов дизайна, если не все, имеют свои аналоги в нашей повседневной жизни, которые мы так хорошо видим и понимаем. Самый эффективный способ понять шаблон дизайна - это узнать их коллег в повседневной жизни. И я верю, что их много.
Luo Jiong Hui 26.02.2018 19:26:27
Неправильный ответ. Вы объясняете внедрение зависимостей, а не IoC. См. Комментарий Рожерио к этому ответу выше
MickyD 29.08.2018 04:25:23
Я согласен. Это DI, а не IoC. По-прежнему получает отклик, потому что это простой подход, но помогает расширить понимание темы.
Mär 21.09.2018 09:15:07
Это объясняет внедрение зависимости. Не иок. Но приятное и понятное объяснение.
Chamin Wickramarathna 19.12.2018 05:55:41

IoC - это инверсия отношений между вашим кодом и сторонним кодом (библиотека / фреймворк):

  • При обычной разработке программного обеспечения вы пишете метод main () и вызываете «библиотечные» методы. Вы контролируете :)
  • В IoC «framework» управляет main () и вызывает ваши методы. Framework контролирует :(

DI (Dependency Injection) рассказывает о том, как управление передается в приложение. Традиционное настольное приложение имело поток управления от вашего приложения (метод main ()) к вызовам других библиотечных методов, но с потоком управления DI инвертируется, поэтому фреймворк заботится о запуске вашего приложения, его инициализации и вызове ваших методов, когда это необходимо.

В итоге ты всегда побеждаешь :)

11
5.11.2015 06:24:45

Я напишу мое простое понимание этих двух терминов:

For quick understanding just read examples*

Внедрение зависимости (DI).
Внедрение зависимости обычно означает передачу объекта, от которого зависит метод, в качестве параметра метода, а не создание метода зависимым объектом .
На практике это означает, что метод не зависит напрямую от конкретной реализации; любая реализация, которая соответствует требованиям, может быть передана в качестве параметра.

С помощью этих объектов сообщают свои зависимости. И весна делает это доступным.
Это приводит к слабосвязанной разработке приложений.

Quick Example:EMPLOYEE OBJECT WHEN CREATED,
              IT WILL AUTOMATICALLY CREATE ADDRESS OBJECT
   (if address is defines as dependency by Employee object)

Контейнер инверсии управления (IoC):
это общая характеристика сред, IOC управляет объектами Java
- от создания экземпляров до уничтожения через BeanFactory.
-Java-компоненты, которые создаются контейнером IoC, называются bean-компонентами, а контейнер IoC управляет областью действия bean-компонента, событиями жизненного цикла и любыми функциями AOP, для которых он был настроен и закодирован.

QUICK EXAMPLE:Inversion of Control is about getting freedom, more flexibility, and less dependency. When you are using a desktop computer, you are slaved (or say, controlled). You have to sit before a screen and look at it. Using keyboard to type and using mouse to navigate. And a bad written software can slave you even more. If you replaced your desktop with a laptop, then you somewhat inverted control. You can easily take it and move around. So now you can control where you are with your computer, instead of computer controlling it,

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

Инверсия управления в качестве руководства по проектированию служит следующим целям:

Происходит разделение выполнения определенной задачи от реализации.
Каждый модуль может сосредоточиться на том, для чего он предназначен.
Модули не делают никаких предположений о том, что делают другие системы, но полагаются на свои контракты.
Замена модулей не оказывает побочного влияния на другие модули.
Я буду держать это здесь абстрактно. Вы можете посетить следующие ссылки для более детального понимания темы.
Хорошее чтиво с примером

Детальное объяснение

22
5.11.2015 06:00:05

Программирование говорения

IoC в простых терминах: это использование интерфейса в качестве определенного элемента (такого как поле или параметр) в качестве подстановочного знака, который может использоваться некоторыми классами. Это позволяет повторно использовать код.

Например, предположим, что у нас есть два класса: Dog и Cat . Оба имеют одинаковые качества / состояния: возраст, размер, вес. Таким образом, вместо создания класса обслуживания, называемого DogService и CatService , я могу создать один, называемый AnimalService, который позволяет использовать Dog и Cat только в том случае, если они используют интерфейс IAnimal .

Однако, прагматично говоря, он имеет некоторые недостатки.

а) Большинство разработчиков не знают, как его использовать . Например, я могу создать класс с именем Customer и автоматически создать (используя инструменты IDE) интерфейс под названием ICustomer . Таким образом, не редко можно найти папку, заполненную классами и интерфейсами, независимо от того, будут ли интерфейсы использоваться повторно или нет. Это называется BLOATED. Некоторые люди могут утверждать, что «возможно, в будущем мы могли бы использовать это». : - |

б) имеет некоторые ограничения. Например, давайте поговорим о случае с Dog и Cat, и я хочу добавить новый сервис (функциональность) только для собак. Допустим, я хочу посчитать, сколько дней мне нужно дрессировать собаку ( trainDays()), для кошки это бесполезно, кошек нельзя дрессировать (я шучу).

б.1) Если я добавлю trainDays()в Сервис AnimalService, то он также работает с кошками и вообще не действует.

б.2) Я могу добавить условие, в trainDays()котором он оценивает, какой класс используется. Но это полностью сломает IoC.

б.3) Я могу создать новый класс обслуживания под названием DogService только для новой функциональности. Но это повысит удобство сопровождения кода, потому что у нас будет два класса обслуживания (со схожей функциональностью) для Dog, и это плохо.

8
27.06.2015 05:46:42
О раздутых классах / интерфейсах: не всегда нужно повторно использовать каждый отдельный интерфейс. Иногда имеет смысл разделить большой интерфейс на несколько меньших, чтобы увидеть его функциональные границы. Меньшие интерфейсы также легче использовать в других реализациях. Также он поощряет вас кодировать интерфейс везде, где это имеет смысл. Рассмотрим разделение интерфейса. Только то, что вы используете интерфейс, не означает, что вы отделены. Единый толстый интерфейс бесполезен. - Просто мои 2 цента :)
M K 31.08.2015 14:18:10

Создание объекта в классе называется тесной связью, Spring удаляет эту зависимость, следуя шаблону проектирования (DI / IOC). В котором объект класса передается в конструкторе, а не в классе. Более того, мы даем ссылочную переменную суперкласса в конструкторе, чтобы определить более общую структуру.

3
27.06.2015 05:42:13

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

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

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

3
16.07.2015 16:06:57

Инверсия управления - это общий принцип, в то время как Dependency Injection реализует этот принцип как шаблон проектирования для построения графа объекта (т.е. конфигурация контролирует, как объекты ссылаются друг на друга, а не сам объект, контролирующий, как получить ссылку на другой объект).

Рассматривая Инверсию Контроля как шаблон проектирования, нам нужно посмотреть на то, что мы инвертируем. Dependency Injection инвертирует управление построением графа объектов. Если сказать в терминах непрофессионала, инверсия управления подразумевает изменение потока управления в программе. Например. В традиционном автономном приложении у нас есть метод main, из которого управление передается сторонним библиотекам (в случае, если мы использовали функцию сторонней библиотеки), но посредством инверсии управления управление передается из кода сторонней библиотеки в наш код , так как мы берем на себя обслуживание сторонней библиотеки. Но есть и другие аспекты, которые необходимо инвертировать в программе - например, вызов методов и потоков для выполнения кода.

Для тех, кто заинтересован в более глубоком рассмотрении Inversion of Control, был опубликован документ с изложением более полной картины Inversion of Control как шаблона проектирования (OfficeFloor: использование шаблонов office для улучшения проектирования программного обеспечения http://doi.acm.org/10.1145/ 2739011.2739013 с бесплатной копией, доступной для загрузки по адресу http://www.officefloor.net/about.html ).

То, что идентифицировано, является следующим отношением:

Инверсия управления (для методов) = впрыск зависимости (состояния) + впрыск продолжения + впрыск резьбы

Резюме вышеуказанных отношений для Инверсии Контроля доступно - http://dzone.com/articles/inversion-of-coupling-control

12
15.03.2019 08:14:30
Это очень четкий ответ. Спасибо за объяснение.
KunYu Tsai 25.08.2019 17:00:04

Отвечая только на первую часть. Что это?

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

25
8.11.2017 04:19:02
Raghvendra Singh 22.07.2018 11:37:50

Для понимания концепции инверсия контроля (IoC) или принцип инверсии зависимости (DIP) включает в себя два действия: абстрагирование и инверсию. Внедрение зависимостей (DI) является лишь одним из немногих методов инверсии.

Чтобы узнать больше об этом вы можете прочитать мой блог здесь

  1. Что это?

Это практика, где вы позволяете фактическому поведению прийти за пределы границы (класс в объектно-ориентированном программировании). Граничный объект знает только его абстракцию (например, интерфейс, абстрактный класс, делегат в объектно-ориентированном программировании).

  1. Какие проблемы это решает?

С точки зрения программирования, IoC пытается решить монолитный код, сделав его модульным, отделив различные его части, и сделав его модульно-тестируемым.

  1. Когда это уместно, а когда нет?

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

3
3.06.2016 02:00:37

Мне нравится это объяснение: http://joelabrahamsson.com/inversion-of-control-an-introduction-with-examples-in-net/

Все начинается просто и показывает примеры кода.

введите описание изображения здесь

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

Разве не достаточно того, что X знает, что использует то, что имеет поведение, методы, свойства и т. Д. Y, не зная, кто на самом деле реализует это поведение?

Извлекая абстрактное определение поведения, используемого X в Y, проиллюстрированного как I ниже, и позволяя потребителю X использовать экземпляр этого вместо Y, он может продолжать делать то, что он делает, не зная специфики о Y.

введите описание изображения здесь

На иллюстрации выше Y реализует I, а X использует экземпляр I. Хотя вполне возможно, что X все еще использует Y, интересно то, что X этого не знает. Он просто знает, что использует то, что реализует I.

Прочитайте статью для получения дополнительной информации и описания преимуществ, таких как:

  • X больше не зависит от Y
  • Более гибкая реализация может быть решена во время выполнения
  • Выделение блока кода, упрощение тестирования

...

10
16.02.2017 02:03:20
Ссылка очень полезна. На самом деле спасибо :)
M Fuat NUROĞLU 18.07.2019 12:03:30

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

Инверсия контроля (IoC) была построена по очень простому принципу, который называется принцип Голливуда . И это говорит о том, что

Не звоните нам, мы вам позвоним

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

Теперь, когда мы обсуждаем принцип IoC, мы забываем о Голливуде. Для IoC должно быть три элемента: Голливуд, ты и задача, подобная осуществлению твоей мечты.

В нашем мире программирования Голливуд представляет собой общую структуру (может быть написана вами или кем-то еще), вы представляете написанный вами код пользователя, а задача представляет собой то, чего вы хотите достичь с помощью своего кода. Теперь вы никогда не запускаете свою задачу самостоятельно, а не в IoC! Скорее вы спроектировали все так, чтобы ваша структура вызывала вашу задачу для вас. Таким образом, вы создали многоразовую структуру, которая может сделать кого-то героем или другого злодеем. Но эта структура всегда отвечает, она знает, когда кого-то выбирать, и что кто-то знает только то, кем он хочет быть.

Пример из реальной жизни будет дан здесь. Предположим, вы хотите разработать веб-приложение. Итак, вы создаете структуру, которая будет обрабатывать все обычные вещи, которые должно обрабатывать веб-приложение, такие как обработка http-запроса, создание меню приложения, обслуживание страниц, управление файлами cookie, запуск событий и т. Д.

И затем вы оставляете несколько хуков в своей инфраструктуре, где вы можете поместить дополнительные коды для создания пользовательского меню, страниц, файлов cookie или регистрации некоторых пользовательских событий и т. Д. При каждом запросе браузера ваша платформа будет запускаться и выполнять ваши пользовательские коды, если они будут подключены, а затем вернуть их обратно. в браузер.

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

Laravel и EJB являются примерами таких рамок.

Справка:

https://martinfowler.com/bliki/InversionOfControl.html

https://en.wikipedia.org/wiki/Inversion_of_control

9
1.10.2017 11:24:20
Наиболее подходящий ответ я нашел здесь.
blueray 15.12.2017 20:00:22

Я нашел очень яркий пример здесь , который объясняет , как "контроль инвертируется.

Классический код (без внедрения зависимостей)

Вот как примерно будет работать код, не использующий DI:

  • Приложению требуется Foo (например, контроллер), поэтому:
  • Приложение создает Foo
  • Приложение вызывает Foo
    • Foo нуждается в Bar (например, услуга), поэтому:
    • Фу создает бар
    • Фу называет бар
      • Бар нужен Bim (сервис, репозиторий,…), поэтому:
      • Бар создает Бим
      • Бар что-то делает

Использование внедрения зависимости

Вот как примерно будет работать код, использующий DI:

  • Приложению нужен Foo, которому нужен Bar, которому нужен Bim, поэтому:
  • Приложение создает Bim
  • Приложение создает бар и дает ему Бим
  • Приложение создает Foo и дает ему Бар
  • Приложение вызывает Foo
    • Фу называет бар
      • Бар что-то делает

Управление зависимостями инвертируется от одного вызываемого к другому вызывающему.

Какие проблемы это решает?

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

Пример: предположим, что ваше приложение хранит загруженный пользователем файл на Google Диске, с DI код вашего контроллера может выглядеть так:

class SomeController
{
    private $storage;

    function __construct(StorageServiceInterface $storage)
    {
        $this->storage = $storage;
    }

    public function myFunction () 
    {
        return $this->storage->getFile($fileName);
    }
}

class GoogleDriveService implements StorageServiceInterface
{
    public function authenticate($user) {}
    public function putFile($file) {}
    public function getFile($file) {}
}

Когда ваши требования изменятся, скажем, вместо GoogleDrive вас попросят использовать Dropbox. Вам нужно только написать реализацию Dropbox для StorageServiceInterface. Вы не вносите никаких изменений в контроллер, пока реализация Dropbox придерживается StorageServiceInterface.

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

Вместо этого, если у вас был класс контроллера для создания объекта хранилища с newключевым словом:

class SomeController
{
    private $storage;

    function __construct()
    {
        $this->storage = new GoogleDriveService();
    }

    public function myFunction () 
    {
        return $this->storage->getFile($fileName);
    }
}

Если вы хотите изменить реализацию Dropbox, вы должны заменить все строки, в которых newпостроен объект GoogleDriveService, и использовать DropboxService. Кроме того, при тестировании класса SomeController конструктор всегда ожидает класс GoogleDriveService и срабатывают фактические методы этого класса.

Когда это уместно, а когда нет? По моему мнению, вы используете DI, когда думаете, что есть (или могут быть) альтернативные реализации класса.

13
4.11.2017 13:27:41
Это должен быть самый правильный ответ, так как только он объясняет, как инвертируется «контроль».
Yarimadam 15.11.2018 13:12:35
лучшее объяснение до сих пор
Ali80 23.02.2020 19:25:27

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

В терминах программирования она передала функцию обратного вызова getProductList()функции, которую вы выполняете - doShopping().

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

14
18.12.2018 05:11:10
Моя жена обычно делает покупки со мной, но я согласен с этим утверждением.
ha9u63ar 24.02.2018 17:02:10
@ ha9u63ar Твоя жена делает покупки у тебя? Ну, это называется агрегация.
Julian 28.01.2019 08:45:42
Если она тоже дает деньги, это называется DI.
San 11.03.2019 13:23:01
Слово «инверсия» - вверх ногами - появилось, когда ваша жена звонит getProductList()вам, чтобы найти источник денег, означает, что контроль находится на вашей стороне. В случае инверсии она будет контролировать, значит, деньги она также предоставит на покупку.
San 11.03.2019 13:32:54

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

5
24.04.2018 12:40:07