Що таке інверсія управління, і коли я повинен її використовувати?


64

Я розробляю нову систему і хочу знати, що таке інверсія управління (МОК), і що ще важливіше, коли її використовувати.

Чи потрібно його реалізовувати за допомогою інтерфейсів чи це можна зробити з класами?


Відповіді:


62

IoC (див. Інверсія контролю у Вікіпедії) застосовується в тих випадках, коли компонент не може виконувати завдання повністю, оскільки не має певної необхідної інформації або функціоналу.

Найпростішим прикладом шаблону IoC можуть бути функції зворотного виклику в C. Наприклад, ви можете оголосити функцію:

void Iterator(void *list, Func* f)

Що повторює listзастосування fфункції до кожного її елемента. IteratorФункція не знає , як буде оброблятися кожен елемент, ви просто вказати функцію в якості аргументу, і він обробляє їх.

Як показано в попередньому прикладі, IoC дозволяє розділити свою програму на окремі компоненти, які не знають один про одного. Однією з найпоширеніших версій IoC є Dependecy Injection .

В ін'єкційній залежності кожний компонент повинен оголосити перелік залежностей, необхідних для виконання його завдання. Під час виконання спеціальний компонент (як правило) під назвою контейнер IoC здійснює зв'язок між цими компонентами. Він намагається надати значення для опублікованих залежностей компонентів.

Ось приклад у псевдокоді:

class Foo 
{ 
   <Require Boo>Constructor(Boo boo){ boo.DoSomething } 
}

У цьому прикладі клас Fooмає конструктор, який вимагає аргументу типу Booдля виконання певної дії.

Ви можете створити екземпляр класу, Fooвикористовуючи код, подібний цьому:

MyContainer.Create(typeof Foo)

MyContainer- це контейнер IoC , який піклується про отримання екземпляра Booта передачу його Fooконструктору.

Підводячи підсумок, IoC дозволяє розділити свою програму на окремі частини. Це добре тому, що:

  • Компоненти можна легко перевірити самостійно.
  • Складність програми може бути зменшена.
  • Ви можете переключити компоненти на іншу реалізацію.

Однак в деяких випадках IoC може зробити складніше зрозумілий код.

Якщо ви хочете побачити хороший приклад використання IoC в реальному світі , перегляньте блок прикладних інтерфейсів Mircosoft Composite та CompositeWPF

Сподіваюся, моє пояснення вам допоможе.

З повагою,
аку


1
Через п'ять років, але все ж .... Це був чудовий опис. Дякую.
Нік Ходжес

4
Не так багато згадується про IoC - це той факт, що код стає важче читати. Читання - пріоритет номер один, якщо ви хочете написати чудове програмне забезпечення. Це навіть перемагає Заповітність. Ви можете роз'єднати код набагато вище його корисності.
Арне Евертссон

Отже, код, який використовує рішення на основі інтерфейсу для всіх його залежностей, також базується на дизайні IoC?
нікель

18

Оскільки я нещодавно сам займався цим питанням і зберігав усі закладки, я дізнався наступне, щоб дізнатися про IOC / DI.

Оригінальна стаття Мартіна Фаулерса про IOC / DI

Деякі поняття, які слід знати спочатку

Відмінна колекція навчальних посібників з МОК / DI

Книга про МОК / DI від Manning Press

Джерело та пояснення того, як створити власний МОК - адже читання вихідного коду - це завжди найкращий спосіб зрозуміти поняття.


4

Привіт, JMS, в основному IoC / DI дозволить вам визначити, яку реалізацію ви використовуєте один раз, і зберегти статичну копію вашого контейнера для посилання кожного разу, коли ви хочете посилатися на нього.

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

IE, скажімо, у вас був інтерфейс для читання потоку, і у вас була реалізація XMLStreamReader та SQLStreamReader. Потім ви можете передати посилання на інтерфейс до своїх методів, а потім у своєму контейнері IoC сказати, який саме використовувати.

Отже, у вас може бути відкритий список ReadPeople (читач IStreamReader) і під час налаштування для вашого контейнера IoC повідомте про це кожен раз, коли ви очікуєте, що IStreamReader використовуватиме SQLStreamReader.

Тоді, якщо згодом ви передумаєте, вам потрібно змінити це лише в одному місці (налаштування вашого контейнера), і не важливо буде, скільки методів вимагає IStreamReader, він завжди отримає стандартний стандарт, про який ви сказали своєму контейнерові служити


3

Скажімо, у вас є валідатор для перевірки того, чи дійсний бізнес у вашій системі. Ваш "BusinessValidator" може мати поле типу AddressValidator, яке підтверджує адресу адреси бізнесу. Якщо ви хочете протестувати BusinessValidator, не виконуючи зовнішній код (тобто код addressValidator), тоді, якщо ви використовували якийсь IoC / DI у ваших рамках, ви можете ослабити "ввести" макет адресуValidator на своє місце, і не потрібно турбуватися про тестування код за межами тестуваного класу.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.