Різниця між впорскуванням залежності (DI) та інверсією управління (IOC)


117

Я бачив багато посилань на залежність впорскування (DI) та інверсії контролю (МОК), але я не знаю, чи є різниця між ними чи ні.

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


Інверсія управління зазвичай відноситься до "контейнерів", тоді як залежність впорскування стосується фактичної структури. Але вони йдуть рука об руку. Я б рекомендував прочитати статтю Мартіна Фаулера, щоб зрозуміти цю тему.
Бен Гофштейн

Введення залежностей - це те, що ви робите, що призводить до структури команди, яка називається Інверсія управління. Вони по своїй суті пов'язані між собою.

2
DI є формою IoC, я дав досить детальне пояснення DI та IoC у цій відповіді

2
Я б сказав, що DI - це особливий випадок МОК. Традиційне управління переходить модуль-> модуль запиту від менеджера модулів, в DI він перетворюється на менеджер модулів-> отримують запитувані залежності від модуля.
Rafał Dowgird

Іншими словами, в основному IoC - це реалізація використання DI. Я правильно це розумію?
dance2die

Відповіді:


53

Визначення

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

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

Працюючи разом

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

Приклади

Одним із прикладів цих концепцій на роботі є плагін в рамках Reflector . Плагіни дуже сильно контролюють систему, хоча програма не знала нічого про додатки під час компіляції. На кожному з цих плагінів викликається поодинокий метод, ініціалізувати, якщо служить пам'ять, яка передає контроль над плагіном. Рамка не знає, що вони будуть робити, вона просто дозволяє їм це робити. Контроль було взято з основної програми та надано компоненту, що виконує конкретну роботу; інверсія управління.

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

У той час для створення плагінів використовувався заводський метод, використовуючи інформацію про конфігурацію, відображення та об’єкт Activator (принаймні в .NET). Сьогодні існують інструменти, MEF для одного, які дозволяють отримати більш широкий спектр варіантів при введенні залежностей, включаючи можливість для програми додатків приймати список плагінів як залежність.

Підсумок

Хоча ці поняття можна використовувати і надавати переваги незалежно, разом вони дозволяють записати набагато більш гнучкий, багаторазовий і перевірений код. Як такі вони є важливими поняттями при розробці об'єктно-орієнтованих рішень.


3
Ні, IoC - це більш давня концепція, і вона не залежить від DI (що не залежить від IoC). Наприклад, візьміть структуру Struts (Java): вона сильно покладається на IoC, але не використовує DI.
Rogério

1
@ Rogério - Ви добре зазначаєте, що ці два поняття не вимагають одне одного. Я оновив свою відповідь, щоб уточнити це, а потім швидко описав, як деякі фреймворки використовують їх разом, щоб ввести код, який є більш вільним.
Чак

Найпростішим додатком IoC, мабуть, буде ActionListener. Замість процедурної обробки коду код обробки подій делегується спеціальному коду. Цим самим перевертаючи керування.
мій

0

Хороша стаття для розуміння МОК та DI http://martinfowler.com/articles/injection.html

МОК (інверсія управління)

IOC означає

  1. кодування до інтерфейсу (один компонент повинен залежати від інтерфейсу іншого компонента, а не від impl), наприклад

    interface iComp_2 {...}
    
    class Comp_1 {
        iComp_2 c2 = ….;
    }
    
  2. видалення конкретного коду для реалізації компонента, наприклад

    Comp_1 {
        iComp_2 c2 = getComp_2_Impl(); // not new Comp_2_Impl();
    }
    

МОК може бути досягнутий одним із наступних:

1. DI (впорскування в залежності)

3 types of DI

1.1 Constructor Injection

1.2 Setter Injection

1.3 Interface Injection

2. Локатор обслуговування

Контейнер DI (залежність впорскування)

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

Імпульс імпульсу після введення залежності: після визначення імпл він створює цей імпульс, спочатку створюючи всі його залежності (вказані у конфігураційному файлі), а потім вводячи ці залежності в цей імпл

Управління життєвим циклом екземпляра: контейнери DI зазвичай зберігають лише посилання на об'єкти, необхідні для управління життєвими циклами, або які повторно використовуються для майбутніх ін'єкцій, як одинакові або маховики. Налаштований для створення нових примірників деяких компонентів для кожного виклику контейнера, контейнер зазвичай просто забуває про створений об'єкт. В іншому випадку сміттєзбірнику буде важко збирати всі ці предмети, коли їх більше не використовувати.


6
Ви справді читали статтю про "ін'єкції"? МОК зовсім не означає, що ця відповідь говорить.
Rogério

-3

Я б сказав, що "Інверсія управління" - це спосіб розробити систему, де всі модулі продумані абстрактними сутностями.

І "Ін'єкція залежностей" - це реалізація, де конкретний зв'язок між різними модулями вирішується в "час виконання".


-4

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

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