Інверсія управління та вприскування залежності


525

Згідно з документом, написаним Мартіном Фаулером , інверсія управління - це принцип, коли керований потік програми інвертується: замість програміста, який управляє потоком програми, зовнішні джерела (рамки, служби, інші компоненти) беруть під контроль це. Це як би ми щось підключили до чогось іншого. Він згадав приклад про EJB 2.0:

Наприклад, інтерфейс Session Bean визначає ejbRemove, ejbPassivate (зберігається у вторинному сховищі) та ejbActivate (відновлюється з пасивного стану). Ви не можете контролювати, коли викликаються ці методи, а саме те, що вони роблять. Контейнер дзвонить нам, ми його не називаємо.

Це призводить до різниці між рамками та бібліотекою:

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

Я думаю, точка зору, що DI є МОК, означає, що залежність об'єкта перевернута: замість того, щоб він контролював власні залежності, життєвий цикл ... щось інше робить це для вас. Але, як ви мені розповідали про DI від руки, DI не обов'язково є МОК. У нас все ще може бути DI та немає МОК.

Однак у цьому документі (з пококапсули, іншої IOC Framework для C / C ++) припускається, що через IOC і DI контейнери IOC та рамки DI набагато перевершують J2EE, оскільки J2EE змішує рамковий код у компоненти , таким чином, не роблячи його звичайним об’єктом Java / C ++ (POJO / POCO).

Інверсія контейнерів управління, окрім схеми вприскування залежності (архів посилання)

Додаткове читання, щоб зрозуміти, у чому полягає проблема зі старою базою розробок на основі компонентів, яка веде до другої статті вище: Чому і що від інверсії управління (Архів посилання)

Моє запитання : Що таке МОК та DI? Я збентежений. На основі покакапсули МОК є чимось більш значущим, ніж просто інверсія управління між об'єктами або програмістами та рамками.


2
Ось хороший запис з цього приводу, IoC проти DI (введення залежності) проти SL (локатор обслуговування): tinyurl.com/kk4be58 - Витяг із URL-адреси: IoC проти DI (введення залежності)? IoC є спільною концепцією , де контроль потоку Перевернута з клієнтського коду в рамки, які «що - то робить для клієнта». SL (Локатор обслуговування) та DI (Вприскування в залежності) - це дві конструкції, що випливають із IoC.
Swab.Jat

Щоб додати свої два центи, якщо вас цікавить, як ін'єкція залежності може бути корисною для теми кафе, я написав статтю про це тут: digigene.com/design-patterns/dependency-injection-coffeeshop
Ali Nem

3
пристойна стаття для початківців asimplify.com/dependency-injection-inversion-control
Khawaja Асім

Інверсія залежності: залежить від абстракцій, а не від конкрементів. Інверсія управління: Main vs Abstraction, і як Main є клеєм систем. Про це говорять кілька хороших дописів: coderstower.com/2019/03/26/… coderstower.com/2019/04/02/… coderstower.com/2019/04/09/…
Даніель Андрес Пелас Лопес

читати про це глибоко, це очистить все martinfowler.com/articles / ...
Дешман

Відповіді:


644

IoC - це загальне поняття, яке означає, а не застосування програми викликає методи в рамках, фреймворк називає реалізацію, яку надає програма.

DI - це форма IoC, де реалізації передаються в об'єкт за допомогою конструкторів / сетерів / служб пошуку, від яких об’єкт буде «залежати», щоб правильно поводитися.

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

DI Frameworks створені для використання DI і можуть визначати інтерфейси (або Анотації на Java), щоб полегшити передачу в реалізації.

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

Дивіться також цю статтю Мартіна Фаулера .


2
Дякую за відповідь. Але інший документ припускає, що з МОК контейнери МОК набагато перевершують EJB, тоді як Мартін Фаулер припускає, що EJB є типовим прикладом МОК.
Amumu

5
Управління EJB - це справді типовий приклад IoC. Ви можете бачити це з того, що життєвим циклом EJB керує контейнер, а не програміст. Програміст не створює і не знищує екземпляр EJB, оскільки управління делеговано серверу . Ось така концепція IoC: зовнішній код контролює, коли ваш код викликається, що, як правило, є зворотним для того, що він робив більшу частину часу.
brandizzi

2
IoC - це загальне поняття, яке означає, а не застосування програми викликає методи в рамках, фреймворк називає реалізацію, яку надає програма. Чи можете ви пояснити це детальніше?
Імад Алазані

21
Принцип Акалі Голівуду : "Не дзвоніть нам, ми вас зателефонуємо". Викликає виклик до рамки, а не програми.
Гарретт Холл

@ImadAlazani, вам краще прочитати статтю, яку додав Гарретт, яка є детальною дискусією про перевернення контролю від коду програми до фреймворку.
MengT

210

Коротше кажучи, IoC - набагато ширший термін, що включає, але не обмежується цим, DI

Термін "Інверсія управління" (IoC) спочатку означав будь-який стиль програмування, де загальний фреймворк або час виконання контролювали потік програми

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

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

Заливання залежностей (DI) означає, що це робиться без втручання об'єкта, як правило, компонент рамки, який передає параметри конструктора та задає властивості.


1
Здається, IoC - це ще один термін для принципу інверсії Depency, ні?
Тодд Ванс

@ToddVance - Так, я думаю, що IoC і DIP - це одне і те ж. DIP і DI - це не одне і те ж. IoC можна зробити без DI, але DI не можна зробити без IoC.
Eljay

2
@ToddVance - Ні, DIP та IoC не є синонімами і не пов'язані між собою.
TSmith

3
Ха, ось чому я тут на цій темі ... "Інверсія управління проти введення залежностей"
Тодд Ванс

50

введіть тут опис зображення
джерело

IoC ( I nversion o f C ontrol): - Це загальний термін і реалізується декількома способами (події, делегати тощо).

DI ( D ependency I njection): - DI є підтипом IoC і реалізується за допомогою конструкторської інжекції, введення сетера або інжекторного введення .

Але Spring підтримує лише два типи:

  • Ін'єкція сетера
    • DI на основі сеттера реалізується за допомогою виклику методів setter на бобі користувача після виклику конструктора без аргументів або статичного фабричного методу без аргументів для інстанціювання їх bean.
  • Інжекція конструктора
    • DI на основі конструктора реалізується шляхом виклику конструктора з декількома аргументами, кожен з яких представляє співавтор. Використовуючи це, ми можемо підтвердити, що введені боби не є нульовими та швидко виходять з ладу (не в процесі компіляції, а не під час виконання), так під час запуску самого застосування ми отримуємо NullPointerException: bean does not exist. Інжекція конструктора - найкраща практика введення залежностей.

1
невірно сказати, що Spring не підтримує введення властивостей. Це робить. І це погана практика, я згоден.
kekko12

Анотація Spring @Autwired - це, на мою думку, спосіб введення властивостей
Sajith

49

DI - це підмножина IoC

  • IoC означає, що об'єкти не створюють інших об'єктів, на яких вони покладаються для своєї роботи. Натомість вони отримують необхідні об'єкти від зовнішньої служби (наприклад, XML-файл або служба однієї програми). Я використовую 2 впровадження IoC - це DI та ServiceLocator.
  • DI означає принцип IoC отримання залежного об'єкта без використання конкретних об'єктів, а абстракцій (інтерфейсів). Це робить усі компоненти ланцюга перевіреними, тому що компонент вищого рівня не залежить від компонента нижчого рівня, тільки від інтерфейсу. Макети реалізують ці інтерфейси.

Ось деякі інші методи досягнення ІОС .


Я б не сказав, що IoC означає не створювати об’єкти. Коли ви зателефонуєте не методом класу безпосередньо, а методом інтерфейсу - це інверсія управління (так як в даному випадку виклик не залежить від коду виклику) і він взагалі не пов'язаний зі створенням об'єкта. Ще один приклад IoC - події та делегати
Євген Горбовий

19

Оскільки всі відповіді наголошують на теорії, я хотів би продемонструвати на прикладі перший підхід:

Припустимо, ми створюємо додаток, який містить функцію для надсилання повідомлень про підтвердження SMS після доставки замовлення. У нас буде два класи, один відповідає за надсилання SMS (SMSService), а інший, відповідальний за фіксацію входів користувача (UIHandler), наш код виглядатиме нижче:

public class SMSService
{
    public void SendSMS(string mobileNumber, string body)
    {
        SendSMSUsingGateway(mobileNumber, body);
    }

    private void SendSMSUsingGateway(string mobileNumber, string body)
    {
        /*implementation for sending SMS using gateway*/
    }
}

public class UIHandler
{
    public void SendConfirmationMsg(string mobileNumber)
    {
        SMSService _SMSService = new SMSService();
        _SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!");
    }
}

Вищезазначена реалізація не є помилковою, але є кілька питань:
-) Припустимо, що в середовищі розробки вам потрібно зберегти SMS-повідомлення, відправлені в текстовий файл, а не використовувати шлюз SMS; ми закінчимо змінити конкретну реалізацію (SMSService) з іншою реалізацією, втрачаємо гнучкість і змушені переписати код у цьому випадку.
-) Ми закінчимо змішування обов'язків класів, наш (UIHandler) ніколи не повинен знати про конкретну реалізацію (SMSService), це потрібно робити поза класами за допомогою «Інтерфейсів». Коли це буде реалізовано, це дасть нам можливість змінити поведінку системи, замінивши (SMSService), що використовується на інший сервіс-макет, який реалізує той самий інтерфейс, ця служба збереже SMS-повідомлення в текстовий файл, а не надсилає на mobileNumber.

Для виправлення вищезазначених проблем ми використовуємо інтерфейси, які будуть реалізовані нашою (SMSService) та новою (MockSMSService), в основному новий інтерфейс (ISMSService) виявить таку ж поведінку обох служб, що і код нижче:

public interface ISMSService
{
    void SendSMS(string phoneNumber, string body);
}

Тоді ми змінимо нашу (SMSService) реалізацію для реалізації інтерфейсу (ISMSService):

public class SMSService : ISMSService
{
    public void SendSMS(string mobileNumber, string body)
    {
        SendSMSUsingGateway(mobileNumber, body);
    }

    private void SendSMSUsingGateway(string mobileNumber, string body)
    {
        /*implementation for sending SMS using gateway*/
        Console.WriteLine("Sending SMS using gateway to mobile: 
        {0}. SMS body: {1}", mobileNumber, body);
    }
}

Тепер ми зможемо створити новий сервіс макетів (MockSMSService) із абсолютно іншою реалізацією за допомогою одного і того ж інтерфейсу:

public class MockSMSService :ISMSService
{
    public void SendSMS(string phoneNumber, string body)
    {
        SaveSMSToFile(phoneNumber,body);
    }

    private void SaveSMSToFile(string mobileNumber, string body)
    {
        /*implementation for saving SMS to a file*/
        Console.WriteLine("Mocking SMS using file to mobile: 
        {0}. SMS body: {1}", mobileNumber, body);
    }
}

На даний момент ми можемо змінити код в (UIHandler), щоб легко використовувати конкретну реалізацію послуги (MockSMSService), як показано нижче:

public class UIHandler
{
    public void SendConfirmationMsg(string mobileNumber)
    {
        ISMSService _SMSService = new MockSMSService();
        _SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!");
    }
}

Ми досягли великої гнучкості та впровадили розділення проблем у нашому коді, але все ж нам потрібно змінити базу коду, щоб переключитися між двома послугами SMS. Тому нам потрібно здійснити введення залежності .

Для цього нам потрібно здійснити зміну до нашого (UIHandler) конструктора класів, щоб передати залежність через нього, зробивши це, код, який використовує (UIHandler), може визначити, яку конкретну реалізацію (ISMSService) використовувати:

public class UIHandler
{
    private readonly ISMSService _SMSService;

    public UIHandler(ISMSService SMSService)
    {
        _SMSService = SMSService;
    }

    public void SendConfirmationMsg(string mobileNumber)
    {
        _SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!");
    }
}

Тепер форма інтерфейсу, яка буде спілкуватися з класом (UIHandler), несе відповідальність, щоб передати, яку реалізацію інтерфейсу (ISMSService) використовувати. Це означає, що ми перевернули контроль, (UIHandler) більше не несе відповідальності вирішувати, яку реалізацію використовувати, як називає код виклику. Ми реалізували принцип інверсії управління, який є одним із його типів.

Код форми інтерфейсу користувача буде таким:

class Program
{
    static void Main(string[] args)
    {
        ISMSService _SMSService = new MockSMSService(); // dependency

        UIHandler _UIHandler = new UIHandler(_SMSService);
        _UIHandler.SendConfirmationMsg("96279544480");

        Console.ReadLine();
    }
}

Відмінне пояснення
ZiviMagic

19

IOC (Inversion Of Control) : Надання контролю контейнеру для отримання екземпляра об'єкта називається Inversion of Control, означає замість того, щоб ви створювали об'єкт за допомогою нового оператора, нехай контейнер це робить для вас.

DI (залежність введення ) : спосіб введення властивостей об'єкту називається залежною ін'єкцією .

У нас є три типи ін'єкції залежності :

  1. Інжекція конструктора
  2. Ін'єкція сетера / геттера
  3. Інжекційне введення

Пружина підтримує лише інжекцію конструктора та впорскування / встановлення геттера .


5

Але весняна документація говорить, що вони однакові.

http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-introduction

У першому рядку " IoC також відомий як ін'єкція залежності (DI) ".


1
Я здогадуюсь, що вони намагалися вирішити, що DI - це дуже широко використовуваний аромат дизайну IoC, який його майже легко можна назвати IoC aka DI - якщо документація не має явних посилань, які дозволяють припустити інше.
ha9u63ar

5
"IoC також відомий як ін'єкція залежності (DI)" ... кінних пір'я!
MikeM

5

IoC - Інверсія управління - це загальний термін, незалежний від мови, він фактично не створює об'єкти, а описує, в якому модному об’єкті створюється.

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


4

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

Існує кілька основних прийомів здійснення інверсії управління. Це:

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

    1). Введення конструктора
    2). Ін'єкція сетера
    3). Інтерфейсна ін'єкція

4

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

Наступними прикладами я намагаюся пояснити обидва ці поняття.

Раніше ми пишемо такий код

Public MyClass{
 DependentClass dependentObject
 /*
  At somewhere in our code we need to instantiate 
  the object with new operator  inorder to use it or perform some method.
  */ 
  dependentObject= new DependentClass();
  dependentObject.someMethod();
}

Завдяки ін'єкції залежності, інжектор залежно піклується про інстанціювання об'єктів

Public MyClass{
 /* Dependency injector will instantiate object*/
 DependentClass dependentObject

 /*
  At somewhere in our code we perform some method. 
  The process of  instantiation will be handled by the dependency injector
 */ 

  dependentObject.someMethod();
}

Наведений вище процес передачі управління якомусь іншому (наприклад, контейнеру) для інстанції та ін'єкції можна назвати інверсією управління, а процес, при якому контейнер МОК вводить залежність для нас, може бути названий ін'єкцією залежності.

МОК - це принцип, коли керований потік програми інвертується: замість програміста, який управляє потоком програми , програма керує потоком, зменшуючи накладні витрати на програміста . Процес, який використовується програмою для введення залежності, називається як DI

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

Також рекомендую прочитати.

Що таке ін'єкційна залежність?

Ви також можете перевірити одну з моїх подібних відповідей тут

Різниця між інверсією введення та керування залежністю


3

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

Це принцип дизайну, в якому Потік управління "отримується" з загальнонаписаної бібліотеки або коду для багаторазового використання.

Щоб краще зрозуміти це, давайте подивимось, як ми звикли кодувати в попередні дні кодування. У процедурній / традиційній мовах бізнес-логіка, як правило, контролює потік програми та "викликає" загальний або багаторазовий код / ​​функції. Наприклад, у простому додатку консолі мій потік управління контролюється вказівками моєї програми, які можуть включати виклики до деяких загальних функцій багаторазового використання.

print ("Please enter your name:");
scan (&name);
print ("Please enter your DOB:");
scan (&dob);

//More print and scan statements
<Do Something Interesting>

//Call a Library function to find the age (common code)
print Age

На відміну від IoC, Frameworks - це багаторазовий код, який "викликає" ділову логіку.

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

Хоча код рамки не знає моєї ділової логіки, він все одно буде знати, як викликати мій код. Це досягається за допомогою подій / делегатів, зворотних дзвінків тощо. Тут управління потоком "перевернуте".

Отже, замість залежності потоку управління на статично пов'язаних об'єктах потік залежить від загального графіка об'єкта та відносин між різними об'єктами.

Dependency Injection - це схема проектування, яка реалізує принцип IoC для вирішення залежностей об'єктів.

Простіше кажучи, коли ви намагаєтеся написати код, ви будете створювати та використовувати різні класи. Один клас (клас A) може використовувати інші класи (клас B та / або D). Отже, клас B і D - залежності класу А.

Простий аналогією буде автомобіль класу. Автомобіль може залежати від інших класів, таких як Двигун, Шини тощо.

Інжекція залежності залежить від того, щоб замість залежних класів (Class Class тут) створювати свої залежності (Class Engine і Class Tire), клас слід вводити конкретний екземпляр залежності.

Давайте розберемося з більш практичним прикладом. Подумайте, що ви пишете власний TextEditor. Крім усього іншого, ви можете мати перевірку орфографії, яка надає користувачеві можливість перевіряти друкарські помилки в його тексті. Проста реалізація такого коду може бути:

Class TextEditor
{

    //Lot of rocket science to create the Editor goes here

    EnglishSpellChecker objSpellCheck;
    String text;

    public void TextEditor()

    {   

        objSpellCheck = new EnglishSpellChecker();

    }

    public ArrayList <typos> CheckSpellings()
    {

        //return Typos;

    }

}

На перший погляд, все виглядає рум’яно. Користувач напише текст. Розробник захопить текст і зателефонує у функцію CheckSpellings і знайде список помилок, які він покаже користувачеві.

Здається, все працює чудово до одного прекрасного дня, коли один користувач почне писати французькою мовою в редакторі.

Щоб забезпечити підтримку більшої кількості мов, нам потрібно мати більше SpellCheckers. Можливо, французька, німецька, іспанська тощо.

Тут ми створили щільно пов'язаний код, причому "англійський" SpellChecker щільно поєднується з нашим TextEditor класом, що означає, що наш клас TextEditor залежить від EnglishSpellChecker або іншими словами EnglishSpellCheker є залежністю для TextEditor. Нам потрібно зняти цю залежність. Крім того, нашому текстовому редактору потрібен спосіб відобразити конкретну посилання будь-якої перевірки орфографії, заснованої на розсуд розробника на час виконання.

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

interface ISpellChecker
{

    Arraylist<typos> CheckSpelling(string Text);

}

Class EnglishSpellChecker : ISpellChecker

{

    public override Arraylist<typos> CheckSpelling(string Text)

    {

        //All Magic goes here.

    }

}



Class FrenchSpellChecker : ISpellChecker

{

    public override Arraylist<typos> CheckSpelling(string Text)

    {

        //All Magic goes here.

    }

}

У нашому прикладі клас TextEditor повинен отримати конкретний екземпляр типу ISpellChecker.

Тепер залежність може бути введена в Constructor, Public Properties або метод.

Давайте спробуємо змінити наш клас за допомогою Constructor DI. Змінений клас TextEditor буде виглядати приблизно так:

Class TextEditor

{

    ISpellChecker objSpellChecker;

    string Text;



    public void TextEditor(ISpellChecker objSC)

    {

        objSpellChecker = objSC;

    }



    public ArrayList <typos> CheckSpellings()

    {

        return objSpellChecker.CheckSpelling();

    }

}

Так що викликовий код під час створення текстового редактора може вводити відповідний SpellChecker Type в екземпляр TextEditor.

Повну статтю ви можете прочитати тут


3

IOC (інверсія управління): надання контролю контейнеру для отримання екземпляра об'єкта називається інверсією управління. Це означає, що замість того, щоб ви створювали об’єкт за допомогою нового оператора , нехай контейнер це робить для вас.

DI ( введення залежності): Передача необхідних параметрів (властивостей) з XML об'єкту (в POJO CLASS) називається введенням залежності.


2

IOC вказує, що зовнішні класи, що керують класами програми, а зовнішні класи означають, що контейнер управляє залежністю між класом програми. Основна концепція МОК полягає в тому, що програмісту не потрібно створювати свої об'єкти, а описувати, як вони повинні бути створені.

Основні завдання, які виконує контейнер IoC: інстанціювати клас додатків. для налаштування об’єкта. зібрати залежності між об'єктами.

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


2

МОК (Інверсія управління) - це в основному концепція дизайну схеми вилучення залежностей та їх розв'язування, щоб зробити потік нелінійним, і дозволити контейнеру / або іншому об'єкту керувати забезпеченням залежностей. Це насправді слідує голлівудському головному "Не дзвони нам, ми зателефонуємо тобі". Тож узагальнення відмінностей.

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

Ін'єкційна залежність: - DI є підтипом МОК і реалізується за допомогою інжектора конструктора, інжектора сетера або методу ін'єкції.

Наступна стаття описує це дуже акуратно.

https://www.codeproject.com/Articles/592372/Dependency-Injection-DI-vs-Inversion-of-Control-IO


1

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

// dependency injection
function doSomething(dependency) {
    // do something with your dependency
}

// in contrast to creating your dependencies yourself
function doSomething() {
    dependency = getDependencySomehow()
}

// inversion of control
application = makeApp(authenticate, handleRequest, sendResponse)
application.run(getRequest())

// in contrast to direct control or a "library" style
application = makeApp()
request = application.getRequest()

if (application.authenticate(request.creds)) {
    response = application.handleRequest(request)
    application.sendResponse(response)
}

Якщо нахилити голову і примружити очі, ви побачите, що DI - це особлива реалізація IoC з особливими проблемами. Замість того, щоб вводити моделі та поведінку в рамки програми чи операції вищого порядку, ви вводите змінні у функцію чи об'єкт.


0

Почнемо з D із SOLID та розглянемо DI та IoC з книги Скотта Міллетта "Професійні моделі дизайну ASP.NET":

Принцип інверсії залежності (DIP)

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

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

Тісно пов'язані з DIP принципом DI та принципом IoC. DI - акт постачання низького рівня або залежного класу за допомогою конструктора, методу чи властивості. Застосовувані разом із DI, ці залежні класи можуть бути перетворені на інтерфейси або абстрактні класи, що призведе до слабко пов'язаних систем, які є дуже перевіреними та легко змінюються.

В IoC потік управління системою інвертується порівняно з процедурним програмуванням. Прикладом цього є контейнер IoC , метою якого є введення послуг у код клієнта, не маючи клієнтського коду, що визначає конкретну реалізацію. Контроль у цьому випадку, який інвертується, є актом клієнта, який отримує послугу.

Міллетт, С (2010). Професійні шаблони дизайну ASP.NET Видавництво Wiley 7-8.


0

// ICO, DI, 10 років тому, це було так:

public class  AuditDAOImpl implements Audit{

    //dependency
    AuditDAO auditDAO = null;
        //Control of the AuditDAO is with AuditDAOImpl because its creating the object
    public AuditDAOImpl () {
        this.auditDAO = new AuditDAO ();
    }
}

Тепер із весною 3,4 або останньою, як нижче

public class  AuditDAOImpl implements Audit{

    //dependency

     //Now control is shifted to Spring. Container find the object and provide it. 
    @Autowired
    AuditDAO auditDAO = null;

}

В цілому керування перевернуто від старої концепції зв'язаного коду до фреймворків, таких як Spring, що робить об'єкт доступним. Отже, це IOC, наскільки я знаю, і введення Dependency, як ви знаєте, коли ми вводимо залежний об'єкт в інший об'єкт за допомогою Constructor або setters. Вводити в основному означає передавати це як аргумент. Навесні у нас є конфігурація на основі XML та анотацій, де ми визначаємо об'єкт bean та передаємо залежний об'єкт стилем введення конструктора чи сеттера.


0

Я знайшов найкращий приклад на Dzone.com, який справді допомагає зрозуміти реальні відмінності між МОК та DI

"IoC - це коли ти, хтось інший, створює для тебе об'єкти". Тож замість того, щоб у вашому коді писати "нове" ключове слово (наприклад, MyCode c = new MyCode ()), об'єкт створює хтось інший. Цей "хтось інший" зазвичай називають контейнером IoC. Це означає, що ми передаємо rrsponsibility (управління) контейнеру, щоб отримати екземпляр об'єкта, називається Inversion of Control., Означає, замість того, щоб ви створювали об'єкт за допомогою нового оператора, нехай контейнер це робить для вас.

   DI(Dependency Injection):  Way of injecting properties to an object is 
   called 
  Dependency injection.
   We have three types of Dependency injection
    1)  Constructor Injection
    2)  Setter/Getter Injection
    3)  Interface Injection
   Spring will support only Constructor Injection and Setter/Getter Injection.

Прочитайте повну статтю IOC та Прочитайте повну статтю DI


0

1) DI є Child-> obj залежить від батьків-obj. Дієслово залежить важливо. 2) МОК є Child-> obj виконувати під платформою. де майданчиком могли бути школа, коледж, клас танцю. Тут виконувати - це діяльність з різними наслідками для будь-якого постачальника платформи.

практичний приклад: `

//DI
child.getSchool();
//IOC
child.perform()// is a stub implemented by dance-school
child.flourish()// is a stub implemented by dance-school/school/

`

-AB


0

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

Впровадження IoC

В об'єктно-орієнтованому програмуванні існує кілька основних прийомів здійснення інверсії управління. Це:

  1. Використання схеми локатора обслуговування Використання інжекції залежностей, наприклад, впорскування конструктора Параметр впорскування Інжекційний інжектор Інжекційний інтерфейс;
  2. Використання контекстуального пошуку;
  3. Використання шаблону дизайну шаблону методу;
  4. Використовуючи шаблон дизайну стратегії

Що стосується ін'єкції залежності

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


0

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

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

У цьому сенсі DI не є тим самим, що і Io C , оскільки мова не йде про управління потоком, однак це свого роду Io * , тобто інверсія власності на створення об'єктів.

Що не так у моєму поясненні DI та IoC?

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