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

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

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

Ответов (25)

Решение

Шаблоны инверсии управления (IoC) и внедрения зависимостей (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 подпись.

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

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

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

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

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

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

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

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

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

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

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

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

И это именно то, что делает 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

}

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

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

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

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

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

Он говорит -

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Выявлены следующие отношения:

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

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

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

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

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

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

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

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

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

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

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

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

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

Laravel и EJB - примеры таких фреймворков.

Ссылка:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Инверсия управления - это показатель смены ответственности в программе.

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

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

function isVarHello($var) {
    return ($var === "Hello");
}

// Responsibility is within the caller
$word = "Hello";
if (isVarHello($word)) {
    $word = "World";
}

Давайте теперь инвертируем элемент управления, переложив ответственность за результат с вызывающего на зависимость:

function changeHelloToWorld(&$var) {
    // Responsibility has been shifted to the dependency
    if ($var === "Hello") {
        $var = "World";
    }
}

$word = "Hello";
changeHelloToWorld($word);

Вот еще один пример использования ООП:

<?php

class Human {
    private $hp = 0.5;

    function consume(Eatable $chunk) {
        // $this->chew($chunk);
        $chunk->unfoldEffectOn($this);
    }

    function incrementHealth() {
        $this->hp++;
    }
    function isHealthy() {}
    function getHungry() {}
    // ...
}

interface Eatable {
    public function unfoldEffectOn($body);
}

class Medicine implements Eatable {
    function unfoldEffectOn($human) {
        // The dependency is now in charge of the human.
        $human->incrementHealth();
        $this->depleted = true;
    }
}

$human = new Human();
$medicine = new Medicine();
if (!$human->isHealthy()) {
    $human->consume($medicine);   
}

var_dump($medicine);
var_dump($human);

*) Отказ от ответственности: реальный человек использует очередь сообщений.

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

...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Плюсы:

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

Минусы:

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

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

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

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

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

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

-

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

-

Примеры

  • Обработка событий. Обработчики событий (что делать) - Возбуждение событий (когда делать)
  • Внедрение зависимости. Код, который создает зависимость (часть «что делать») - создание экземпляра и внедрение этой зависимости для клиентов, когда это необходимо, о чем обычно заботятся инструменты DI, такие как Dagger (часть «когда-делать-часть»).
  • Интерфейсы. Компонентный клиент (часть выполнения) - реализация интерфейса компонента (часть выполнения)
  • xUnit приспособление. Настройка и TearDown (часть, что делать) - фреймворк xUnit вызывает Setup в начале и TearDown в конце (часть, когда нужно сделать)
  • Шаблон проектирования метода шаблона. шаблонный метод when-to-do part - реализация примитивного подкласса, часть того, что делать
  • Методы контейнера DLL в COM. DllMain, DllCanUnload и т. Д. (Что делать) - COM / OS (когда делать)

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

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

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