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

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

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

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

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

+1372
источник

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

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

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

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

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

+578
источник
другие ответы

Связанные вопросы


Похожие вопросы

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

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

  1. Отделяйте часть " что делать" от части " когда делать".
  2. Убедитесь, что когда часть знает как можно меньше о какой части; и наоборот.

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

-

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

-

Примеры

  • Обработка событий. Обработчики событий (часть "что нужно делать") - "Возникновение событий" (часть "когда нужно делать")
  • Интерфейсы. Компонентный клиент (часть при выполнении) - реализация интерфейса компонента (часть, что нужно сделать)
  • xUnit крепеж. Настройка и TearDown (часть "что делать") - платформы xUnit вызывают программу установки в начале и TearDown в конце (часть "когда нужно делать")
  • Шаблон метода проектирования шаблона. часть шаблона метода when-to-do - примитивная реализация подкласса what-to-do
  • Методы контейнера DLL в COM. DllMain, DllCanUnload и т.д. (Часть "что делать") - COM/OS (часть "когда делать")
+400
источник

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

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

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

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

+146
источник

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

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

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

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

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

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

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

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

+99
источник

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

Плюсы:

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

Минусы:

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

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

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

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

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

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

+64
источник

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

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

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

+43
источник

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

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

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

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

+41
источник

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

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

+40
источник
  • Инверсия управления - это шаблон, используемый для развязки компонентов и слоев в системе. Шаблон реализуется путем ввода зависимостей в компонент при его построении. Эти зависимости обычно предоставляются в качестве интерфейсов для дальнейшей развязки и обеспечения возможности тестирования. Контейнеры IoC/DI, такие как Castle Windsor, Unity, являются инструментами (библиотеками), которые могут использоваться для обеспечения IoC. Эти инструменты предоставляют расширенные функции, помимо простого управления зависимостями, включая продолжительность жизни, AOP/перехват, политику и т.д.

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

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

+25
источник

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

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

+22
источник

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

For quick understanding just read examples*

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

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, называются beans, а контейнер 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.

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

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

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

Подробное объяснение

+21
источник

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

Короче Control получает инвертированный от Programmer к контейнеру. Таким образом, он называется инверсией управления.

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

+17
источник

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

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

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

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

Пусть инвертирует управление.

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

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

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

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

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

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

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

Пример: -

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
источник

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

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

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

+16
источник

Похоже, что самая запутанная вещь о "IoC" - акроним и имя, для которого оно стоит, - это то, что он слишком гламур с именем - почти шумовое название.

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

+15
источник

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

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

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

+12
источник

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

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

Это говорит -

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

+11
источник

IoC означает инвертирование отношения между вашим кодом и сторонним кодом (library/framework):

  • В обычной разработке s/w вы пишете метод main() и называете методы "библиотеки". Вы находятся в управлении:)
  • В IoC "framework" управляет main() и вызывает ваши методы. Элемент Framework находится в управлении: (

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

В конце концов вы всегда выигрываете:)

+11
источник

Инверсия управления - это общий принцип, в то время как 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

+11
источник

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

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

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

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

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

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

  • Приложению нужен Foo, которому нужен Bar, которому нужен Bim, поэтому:
  • Приложение создает Bim
  • Приложение создает бар и дает ему Бим
  • Приложение создает Foo и дает ему Bar
  • Приложение вызывает 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, когда думаете, что есть (или могут быть) альтернативные реализации класса.

+10
источник

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

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

enter image description here

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

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

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

enter image description here

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

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

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

...

+9
источник

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

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

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

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

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

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

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

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

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

+8
источник

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

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

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

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

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

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

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

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

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

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

Ссылка:

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

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

+7
источник

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

+4
источник
  • Итак, номер 1 выше. Что такое инверсия управления?

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

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

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

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

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

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

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

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

+3
источник

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

+3
источник

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

Решает проблему ручного изменения каждого экземпляра объекта одного типа на другой.

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

+3
источник

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

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

  • Что это такое?

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

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

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

  1. Когда это подходит, а когда нет?

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

+3
источник
  • 1
  • 2

Посмотрите другие вопросы по меткам или Задайте вопрос