Вопрос

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

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

Решение

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

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

public class TextEditor {

    private SpellChecker checker;

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

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

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 подпись.

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

Другие советы

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

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

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

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

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

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

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

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

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

--

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

--

Примеры

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Плюсы:

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

Минусы:

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

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

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

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

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

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

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

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

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

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

Без участия МоК:вы просите "яблоко", и вам всегда подают яблоко, когда вы просите еще.

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

Таким образом, очевидно, что МоК предпочтительнее, если вам нравятся сорта.

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

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

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

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

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

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

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, называются beans, а Контейнер IoC управляет областью действия компонента, событиями жизненного цикла и любыми функциями 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.

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

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

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

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

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

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

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

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

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

Допустим, мы назначаем какую-то встречу в каком-то отеле.

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

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

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

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

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

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

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

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

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

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

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

Пример:-

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

}

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

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

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

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

Кажется, что самое запутанное в аббревиатуре "МоК" и названии, за которым она стоит, заключается в том, что это слишком гламурное название - почти шумовое.

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

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

  • При обычной s / w разработке вы пишете главный () метод и вызовите методы "библиотеки". Ты вы все контролируете :)
  • В МоК "рамочный" контроль главный () и вызывает ваши методы.Тот Самый Структура находится под контролем :(

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

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

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

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

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

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

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

В нем говорится -

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

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

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

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

Выявлена следующая взаимосвязь:

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

Доступно краткое изложение приведенного выше соотношения для инверсии управления - http://dzone.com/articles/inversion-of-coupling-control

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

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

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

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

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

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

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

Вместо этого, если бы у вас был класс controller для создания объекта storage с помощью 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, когда считаете, что существуют (или могут быть) альтернативные реализации класса.

Говорящий о программировании

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

Например, предположим, что у нас есть два класса : Собака и Кошка.Оба обладают одинаковыми качествами / состояниями:возраст, размер, вес.Таким образом, вместо создания класса сервиса, вызываемого Обслуживание собак и Кошачий сервис, я могу создать один под названием Обслуживание животных это позволяет использовать Dog и Cat только в том случае, если они используют интерфейс Животное.

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

а) Большинство разработчиков не знают, как им пользоваться.Например, я могу создать класс под названием Клиент и Я могу создавать автоматически (используя инструменты IDE) интерфейс, называемый Клиент ICustomer.Таким образом, нередко можно найти папку, заполненную классами и интерфейсами, независимо от того, будут ли интерфейсы использоваться повторно или нет.Это называется РАЗДУТЫМ.Некоторые люди могли бы возразить, что "возможно, в будущем мы смогли бы это использовать".:-|

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

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

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

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

Мне нравится это объяснение: 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
  • Более гибкая реализация может быть решена во время выполнения
  • Изоляция блока кода, упрощение тестирования

...

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

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

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

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

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

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

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

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

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

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

Ссылка:

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

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

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

  1. Итак, номер 1 выше. Что такое Инверсия контроля?

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  1. Что это?

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top