Інверсія управління (IoC) може бути дуже заплутаною, коли вона вперше зустрічається.
- Що це?
- Яку проблему вона вирішує?
- Коли це доцільно використовувати, а коли ні?
Інверсія управління (IoC) може бути дуже заплутаною, коли вона вперше зустрічається.
Відповіді:
Шаблони інверсії керування (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;
}
}
У першому прикладі коду ми instantiating SpellChecker
( this.checker = new SpellChecker();
), що означає, що TextEditor
клас безпосередньо залежить від SpellChecker
класу.
У другому прикладі коду ми створюємо абстракцію, маючи SpellChecker
клас залежності в TextEditor
підписі конструктора 's (не ініціалізуючи залежність у класі). Це дозволяє нам викликати залежність, а потім передавати її в клас TextEditor так:
SpellChecker sc = new SpellChecker; // dependency
TextEditor textEditor = new TextEditor(sc);
Тепер клієнт, що створює TextEditor
клас, має контроль над тим, яку SpellChecker
реалізацію використовувати, оскільки ми вводимо залежність у TextEditor
підпис.
Інверсія управління - це те, що ви отримуєте при відкликанні програми, наприклад, як програма gui.
Наприклад, у старому шкільному меню ви можете мати:
print "enter your name"
read name
print "enter your address"
read address
etc...
store in database
тим самим контролюючи потік взаємодії користувачів.
У програмі GUI або щось подібне ми говоримо:
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
Отже, тепер управління перевернуто ... замість того, щоб комп'ютер приймав користувацькі введення у фіксованому порядку, користувач контролює порядок введення даних та коли дані зберігаються в базі даних.
В основному все , що має цикл подій, зворотний виклик або виконує тригери, належить до цієї категорії.
Що таке інверсія управління?
Якщо дотримуватися цих простих двох кроків, ви зробили інверсію управління:
Для кожного з цих кроків можливе декілька методів на основі технології / мови, яку ви використовуєте для своєї реалізації.
-
Інверсія частина Инверсии управління (IoC) є заплутаною річчю; тому що інверсія - відносний термін. Найкращий спосіб зрозуміти IoC - забути про це слово!
-
Приклади
what-to-do
іwhen-to-do
Інверсія управління - це розділення проблем.
Без IoC : у вас портативний комп'ютер, і ви випадково зламаєте екран. І чорт, ви знайдете той же екран екрана ноутбука ніде на ринку. Так ти застряг.
За допомогою IoC : у вас настільний комп'ютер, і ви випадково зламаєте екран. Ви виявите, що можете просто захопити практично будь-який настільний монітор з ринку, і він добре працює з вашим робочим столом.
У цьому випадку ваш робочий стіл успішно реалізує IoC. Він приймає різні типи моніторів, тоді як ноутбук цього не робить, йому потрібен певний екран, щоб виправитись.
Інверсія контролю (або IoC) - це отримання свободи (Ви одружуєтеся, втратили свободу і вас контролюють. Ви розлучилися, ви щойно запровадили Інверсію контролю. Ось, що ми назвали, "розв'язали". Гарна комп'ютерна система перешкоджає дуже близьким стосункам.) Більше гнучкості (На кухні у вашому офісі подається лише чиста вода з-під крана, це ваш єдиний вибір, коли ви хочете пити. Ваш начальник впровадив Інверсію управління, встановивши нову кавоварку. Тепер ви отримаєте гнучкість вибору води або кави.) та менша залежність (У вашого партнера є робота, у вас немає роботи, ви фінансово залежите від свого партнера, тому ви контролюєте. Ви знайдете роботу, впровадили Інверсію контролю. Гарна комп'ютерна система заохочує залежність.)
Використовуючи настільний комп'ютер, ви невільницю (або скажімо, керуєте). Ви повинні сісти перед екраном і подивитися на нього. Використання клавіатури для набору та використання миші для навігації. І погано написане програмне забезпечення може невільнити вас ще більше. Якщо ви заміните робочий стіл ноутбуком, то ви дещо перевернули управління. Ви можете легко взяти його і пересуватися. Тож тепер ви можете контролювати, де ви знаходитесь зі своїм комп’ютером, замість того, щоб комп'ютер керував ним.
Реалізуючи Inversion of Control, споживач програмного забезпечення / об’єктів отримує більше елементів керування / опцій над програмним забезпеченням / об'єктами, замість того, щоб контролюватись або мати менше можливостей.
Маючи на увазі вищезазначені ідеї. Ми все ще пропускаємо ключову частину IoC. У сценарії IoC споживач програмного забезпечення / об'єктів - це складні рамки. Це означає, що створений вами код не називається самим. Тепер пояснимо, чому цей спосіб працює краще для веб-програми.
Припустимо, ваш код - це група працівників. Їм потрібно побудувати автомобіль. Ці працівники потребують місця та інструментів (програмного забезпечення) для побудови машини. Традиційні рамки програмного забезпечення будуть як гараж з великою кількістю інструментів. Тож робітники повинні скласти план самостійно і використовувати інструменти для побудови машини. Побудувати автомобіль - справа непроста, працівникам буде дуже важко планувати та співпрацювати належним чином. сучаснийПрограмне забезпечення буде подібне до сучасного автомобільного заводу зі всіма зручностями та менеджерами. Робітники не повинні складати ніякого плану, менеджери (частина рамки, вони найрозумніші люди і склали найскладніший план) допоможуть скоординуватись, щоб працівники знали, коли робити свою роботу (фреймворк називає ваш код). Працівники просто повинні бути досить гнучкими, щоб користуватися будь-якими інструментами, які надають їм менеджери (за допомогою ін'єкції залежності).
Хоча робітники надають управління управлінням проектом на найвищому рівні менеджерам (рамки). Але добре, щоб допомогли деякі професіонали. Це ідея ІОК по-справжньому походить.
Сучасні веб-додатки з архітектурою MVC залежать від основи для маршрутизації URL-адрес та встановлення контролерів на місце для виклику фреймворку.
Заливання залежності та інверсія управління пов'язані. Інжекція залежностей знаходиться на мікрорівні, а інверсія управління - на макрорівні . Ви повинні з'їсти кожен шматочок (реалізуйте DI), щоб закінчити їжу (реалізуйте IoC).
Перш ніж використовувати Inversion of Control, ви повинні добре знати, що він має свої плюси і мінуси, і ви повинні знати, для чого ви його використовуєте, якщо це робите.
Плюси:
Мінуси:
Особисто я бачу сильні моменти IoC, і мені вони дуже подобаються, але я схильний уникати IoC, коли це можливо, тому що це перетворює ваше програмне забезпечення в колекцію класів, які вже не становлять "справжню" програму, а просто щось, що потрібно скласти разом Конфігурація XML або метадані анотацій, і без них розпадаються (і розпадаються).
Стаття у Вікіпедії . Для мене інверсія управління перетворює ваш послідовно написаний код і перетворює його в структуру делегування. Замість того, щоб ваша програма явно контролювала все, ваша програма встановлює клас або бібліотеку з певними функціями, які потрібно викликати, коли відбуваються певні речі.
Він вирішує дублювання коду. Наприклад, за старих часів ви вручну писали б свій власний цикл подій, оглядаючи системні бібліотеки для нових подій. На сьогоднішній день у більшості сучасних API ви просто повідомляєте системним бібліотекам, які події вас цікавлять, і вони повідомлять вас про те, коли вони відбудуться.
Інверсія управління - це практичний спосіб зменшити дублювання коду, і якщо ви виявите, що копіюєте цілий метод і змінюєте лише невеликий фрагмент коду, ви можете розглянути можливість його боротьби з інверсією управління. Інверсія управління полегшується багатьма мовами завдяки концепції делегатів, інтерфейсів чи навіть необроблених покажчиків функцій.
Використовувати його не доцільно у всіх випадках, оскільки за потоком програми може бути важче прослідкувати, коли написано таким чином. Це корисний спосіб проектування методів при написанні бібліотеки, яка буде повторно використана, але її слід використовувати ощадливо в основі вашої власної програми, якщо це дійсно не вирішує проблему дублювання коду.
Але я думаю, що ви повинні бути дуже обережні з цим. Якщо ви зловживаєте цим шаблоном, ви зробите дуже складний дизайн і ще складніший код.
Як у цьому прикладі з TextEditor: якщо у вас є лише один SpellChecker, можливо, це не дуже потрібно використовувати IoC? Якщо вам не потрібно писати одиничні тести чи щось таке ...
У будь-якому випадку: будьте розумні. Модель дизайну - це добра практика, але не Біблія, яку слід проповідувати. Не скріплюйте його скрізь.
IoC / DI для мене витісняє залежність від об'єктів, що викликають. Супер просто.
Відповідь, що не займається технікою, зможе поміняти двигун в машині безпосередньо перед тим, як увімкнути його. Якщо все підходить правильно (інтерфейс), ви добре.
Припустимо, ти об’єкт. І ти йдеш у ресторан:
Без IoC : ви просите "яблуко", і вам завжди подають яблуко, коли ви просите більше.
З IoC : Ви можете попросити "фрукти". Ви можете отримувати різні фрукти щоразу, коли вас подають. наприклад, яблуко, апельсин або кавун.
Тому, очевидно, IoC вважається кращим, коли вам подобаються сорти.
Інверсія управління - це схема, яка використовується для роз'єднання компонентів і шарів у системі. Шаблон реалізується за допомогою введення залежностей у компонент при його побудові. Ці залежності, як правило, надаються як інтерфейси для подальшої розв'язки та для підтвердження тестабельності. Контейнери IoC / DI, такі як Castle Windsor, Unity - це інструменти (бібліотеки), які можна використовувати для надання IoC. Ці інструменти надають розширені можливості вище та поза простим управлінням залежностями, включаючи термін експлуатації, AOP / перехоплення, політику тощо.
а. Звільняє компонент від відповідальності за управління його залежностями.
б. Надає можливість міняти реалізацією залежностей у різних середовищах.
c. Дозволяє перевірити компонент через глузування залежностей.
г. Забезпечує механізм обміну ресурсами протягом програми.
а. Критично важливо робити тестові розробки. Без IoC це може бути важко перевірити, оскільки тестовані компоненти сильно поєднані з рештою системи.
б. Критичний при розробці модульних систем. Модульна система - це система, компоненти якої можна замінити, не вимагаючи перекомпіляції.
c. Критично важливо, якщо є багато наскрізних проблем, з якими потрібно вирішити, зокрема, у корпоративній програмі.
Відповідаючи лише на першу частину. Що це?
Інверсія управління (IoC) означає створити екземпляри залежностей першого та останнього примірника класу (необов'язково вводити їх через конструктор), а не створювати спочатку екземпляр класу, а потім екземпляр класу, створюючи екземпляри залежностей. Таким чином, інверсія управління інвертує на потік управління програми. Замість того , щоб на викликається керуючому в потік управління (при створенні залежностей), то абонент контролює потік управління програми .
Я запишу своє просте розуміння цих двох термінів:
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):
Це загальна характеристика рамок, МОК управляє об'єктами java
- від інстанції до знищення через його BeanFactory.
-Java компоненти, які інстанціюються контейнером IoC, називають квасолею, а контейнер 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
.
Реалізуючи Inversion of Control, споживач програмного забезпечення / об’єктів отримує більше елементів керування / опцій над програмним забезпеченням / об'єктами, замість того, щоб контролюватись або мати менше можливостей.
Інверсія управління як настанова проектування служить наступним цілям:
Відбувається роз'єднання виконання певного завдання від реалізації.
Кожен модуль може зосередитись на тому, для чого він призначений.
Модулі не передбачають припущень щодо того, що роблять інші системи, але покладаються на їх контракти.
Заміна модулів не побічно впливає на інші модулі.
Я буду тримати абстрактні речі тут. Ви можете перейти за наступними посиланнями для детального розуміння теми.
Гарне прочитання з прикладом
Я погоджуюся з NilObject , але я хотів би додати до цього:
якщо ви виявите, що копіюєте весь метод і змінюєте лише невеликий фрагмент коду, ви можете розглянути питання щодо його інверсії управління
Якщо ви виявляєте, що копіюєте та вставляєте код навколо, ви майже завжди робите щось не так. Кодифікований як принцип дизайну Раз і тільки один раз .
Наприклад, завдання №1 - створити об’єкт. Без концепції МОК завдання №1 має бути виконано програмістом. Але з концепцією МОК завдання №1 буде виконано контейнером.
Коротше кажучи, управління перетворюється з програміста на контейнер. Отже, це називається інверсією управління.
Я знайшов один хороший приклад тут .
Скажімо, що ми проводимо зустріч у якомусь готелі.
Багато людей, багато кафе, води, багато пластикових стаканчиків.
Коли хтось хоче пити, вона наповнює чашку, п’є і кидає чашку на підлогу.
Через годину чи щось у нас є підлога, покрита пластиковими чашками та водою.
Нехай інвертне управління.
Ту ж зустріч там же, але замість пластикових чашок у нас є офіціант із однією скляною чашкою (Singleton)
і вона весь час пропонує гостям пити.
Коли хтось хоче пити, вона дістає зі стакана офіціанта, випиває і повертає назад офіціанту.
Залишаючи осторонь питання про гігієнічну, остання форма контролю питного процесу набагато ефективніша та економічна.
І саме це робить 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" та назві, за якою вона стоїть, - це те, що це занадто гламурне ім'я - майже шумне ім'я.
Чи справді нам потрібна назва, за допомогою якої можна описати різницю між процедурним та подійним програмуванням? Гаразд, якщо нам потрібно, але чи потрібно вибирати нове ім’я "більше, ніж життя", яке більше бентежить, ніж вирішує?
Інверсія контролю - це коли ти йдеш до продуктового магазину, а дружина дає тобі список продуктів, які можна придбати.
З точки зору програмування, вона передала функцію зворотного виклику функції, getProductList()
яку ви виконуєте - doShopping()
.
Це дозволяє користувачеві функції визначати деякі його частини, роблячи її більш гнучкою.
getProductList()
вам, щоб знайти джерело грошей, означає, що контроль у вас поруч. У випадку інверсії, яку вона контролюватиме, значить, гроші, які вона надасть, щоб придбати.
Я знайшов дуже яскравий приклад тут , який пояснює , як "контроль інвертується.
Класичний код (без введення залежності)
Ось як приблизно буде працювати код, що не використовує DI:
Використання ін'єкції залежності
Ось як приблизно буде працювати код з використанням DI:
Контроль залежностей перевернуто від одного виклику до виклику.
Які проблеми вона вирішує?
Ін'єкційна залежність дозволяє легко поміняти місцями з різною реалізацією введених класів. Під час тестування одиниць ви можете вводити фіктивну реалізацію, що робить тестування значно простішим.
Напр .: Припустимо, що ваша програма зберігає завантажений користувачем файл на Диску 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. Вам потрібно лише написати реалізацію папки для інтерфейсу StorageServiceInterface. Ви не вносите жодних змін у контролер до тих пір, поки реалізація Dropbox дотримується інтерфейсу StorageServiceInterface.
Під час тестування ви можете створити макет для StorageServiceInterface за допомогою макетної реалізації, де всі методи повертають нульове значення (або будь-яке заздалегідь визначене значення відповідно до вашої вимоги тестування).
Натомість, якщо у вас був клас контролера, щоб сконструювати об’єкт зберігання з таким 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, коли думаєш, що існують (або можуть бути) альтернативні реалізації класу.
Тут можна знайти дуже просте письмове пояснення
http://binstock.blogspot.in/2008/01/excellent-explanation-of-dependency.html
Він говорить -
"Будь-яке нетривіальне додаток складається з двох або більше класів, які співпрацюють один з одним для виконання певної логіки бізнесу. Традиційно кожен об'єкт відповідає за отримання власних посилань на об'єкти, з якими співпрацює (його залежності). Об'єкти дають свої залежності на час створення деяким зовнішнім об'єктом, який координує кожен об'єкт у системі. Іншими словами, залежності вводяться в об'єкти ".
Інверсія управління є загальним принципом, в той час як залежність введення реалізує цей принцип як модель дизайну для побудови графіків об'єкта (тобто конфігурація контролює те, як об'єкти посилаються один на одного, а не сам об'єкт, який контролює, як отримати посилання на інший об'єкт).
Дивлячись на Інверсію управління як на модель дизайну, нам потрібно подивитися, що ми перетворюємо. Залежність впорскування інвертує управління побудовою графіка об'єктів. Якщо сказати терміном непростого, інверсія управління передбачає зміну потоку управління в програмі. Напр. У традиційному автономному додатку у нас є основний метод, з якого управління передається іншим стороннім бібліотекам (на випадок, якщо ми використали функцію сторонньої бібліотеки), але через інверсію управління керуванням передається з коду бібліотеки третьої сторони до нашого коду , оскільки ми приймаємо послугу бібліотеки третьої сторони. Але є й інші аспекти, які потрібно перевернути в межах програми - наприклад, виклик методів і потоків для виконання коду.
Для тих, хто цікавиться більшою глибиною Inversion of Control, був опублікований документ, в якому викладена більш повна картина Інверсії управління як структури дизайну (OfficeFloor: використання шаблонів офісу для вдосконалення дизайну програмного забезпечення http://doi.acm.org/10.1145/ 2739011.2739013 з безкоштовною копією, доступною для завантаження з http://www.officefloor.net/about.html ).
Виявлено наступні відносини:
Інверсія управління (для методів) = залежність (стан) впорскування + продовження впорскування + впорскування нитки
Підсумок вищезазначених взаємозв'язків щодо інверсії управління доступний - http://dzone.com/articles/inversion-of-coupling-control
IoC полягає в інвертуванні зв'язку між вашим кодом та стороннім кодом (бібліотека / фреймворк):
DI (залежність впорскування) - це про те, як управління протікає в додатку. Традиційна програма для настільних ПК мала контрольний потік від вашої програми (основного () методу) до інших викликів методів бібліотеки, але, якщо потік управління DI інвертований, цей фреймворк дбає про запуск програми, ініціалізацію його та виклик ваших методів, коли потрібно.
Зрештою, ви завжди виграєте :)
Мені подобається це пояснення: 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 цього не знає. Він просто знає, що використовує щось, що реалізує я.
Прочитайте статтю для отримання додаткової інформації та опису переваг, таких як:
...
Я розумію, що тут вже була дана відповідь. Але я все-таки думаю, що деякі основи щодо інверсії управління повинні бути обговорені тут для майбутніх читачів.
Інверсія управління (IoC) була побудована за дуже простим принципом під назвою Голівудський принцип . І це говорить про те,
Не дзвоніть нам, ми зателефонуємо вам
Це означає, що не їдьте в Голлівуд, щоб здійснити свою мрію, а якщо ви гідні, то Голлівуд знайде вас і здійснить вашу мрію. Досить перевернута, так?
Тепер, коли ми обговорюємо принцип ІОК, ми забуваємо про Голлівуд. Для IoC повинно бути три стихії, голлівудський, ти і таке завдання, як виконати свою мрію.
У нашому світі програмування Голлівуд представляє собою загальну основу (може бути написана вами чи ким-небудь іншим), ви представляєте код користувача, який ви написали, а завдання представляють те, що ви хочете виконати зі своїм кодом. Тепер ви ніколи не ходите самостійно запускати завдання, а не в IoC! Швидше ви створили все так, щоб ваша рамка викликала ваше завдання. Таким чином, ви створили основу для багаторазового використання, яка може зробити когось героєм чи іншим лиходієм. Але ця основа завжди відповідає, вона знає, коли когось обрати, і хтось знає лише те, що хоче бути.
Тут можна навести приклад із реального життя. Припустимо, ви хочете розробити веб-додаток. Отже, ви створюєте рамку, яка буде обробляти всі звичайні речі, якими має працювати веб-додаток, як обробка http-запиту, створення меню програми, сервірування сторінок, керування файлами cookie, запуск подій тощо.
І тоді ви залишаєте кілька гачків у вашій рамці, куди ви можете помістити подальші коди для створення користувацького меню, сторінок, файлів cookie або реєстрації деяких подій користувача тощо. На кожен запит браузера ваша рамка запускається та виконує ваші користувацькі коди, якщо підключена, потім обслуговуватиме її назад до браузера.
Отже, ідея досить проста. Замість того, щоб створювати користувальницьку програму, яка контролюватиме все, спочатку ви створюєте багаторазовий фреймворк, який контролюватиме все, потім записуйте власні коди та підключаєте їх до рамки, щоб виконати ці вчасно.
Laravel та EJB - приклади таких рамок.
Довідка:
Програмування говоріння
IoC у простому розумінні: це використання Інтерфейсу як способу конкретного чогось (такого поля чи параметра) як підстановочного символу, який може використовуватися деякими класами. Це дозволяє повторно використовувати код.
Наприклад, скажімо, що у нас є два класи: Собака та Кішка . Обидва мають однакові якості / стани: вік, розмір, вага. Тож замість створення класу сервісів, який називається DogService та CatService , я можу створити єдиний під назвою AnimalService, який дозволяє використовувати собак і кішок, лише якщо вони використовують інтерфейс IAnimal .
Однак, прагматично кажучи, це має певний зворотній бік.
a) Більшість розробників не знають, як ним користуватися . Наприклад, я можу створити клас під назвою Customer і я можу автоматично створити (за допомогою інструментів IDE) інтерфейс під назвою ICustomer . Отже, не рідко можна знайти папку, наповнену класами та інтерфейсами, незалежно від того, будуть використані інтерфейси чи ні. Це називається БЛОТОВАНО. Деякі люди можуть стверджувати, що "можливо, у майбутньому ми можемо ним скористатися". : - |
б) Він має деякі обмеження. Наприклад, поговоримо про випадок Собаки та Кішки, і я хочу додати нову послугу (функціональність) лише для собак. Скажімо, я хочу обчислити кількість днів, які мені потрібні для дресирування собаки ( trainDays()
), для котів це марно, котів не можна тренувати (я жартую).
b.1) Якщо я додаю trainDays()
до Service AnimalService, він також працює з кішками, і це зовсім не дійсно.
b.2) Я можу додати умову, в trainDays()
якій він оцінює, який клас використовується. Але він повністю порушить IoC.
b.3) Я можу створити новий клас сервісу під назвою DogService лише для нового функціоналу. Але це збільшить ремонтопридатність коду, оскільки у нас буде два класи обслуговування (з подібною функціональністю) для Dog, і це погано.
Я прочитав багато відповідей на це, але якщо хтось все ще плутається і потребує плюс ультра "лайманського терміна", щоб пояснити IoC, ось мій:
Уявіть, що батько та дитина розмовляють між собою.
Без IoC:
* Батько : Ви можете говорити лише тоді, коли я задаю вам запитання, і ви можете діяти лише тоді, коли я даю вам дозвіл.
Батько : Це означає, що ви не можете запитати мене, чи можете ви їсти, грати, ходити до ванної кімнати чи навіть спати, якщо я вас не прошу.
Батько : Хочеш їсти?
Дитина : Ні.
Батько : Гаразд, я повернусь. Чекай на мене.
Дитина : (Хоче грати, але оскільки у батька питання не виникає, дитина нічого не може зробити).
Через 1 годину ...
Батько : Я повернувся. Ви хочете пограти?
Дитина : Так.
Батько : дозвіл надано.
Дитина : (нарешті вміє грати).
Цей простий сценарій пояснює, що управління зосереджено на батьківському. Свобода дитини обмежена і сильно залежить від питання батька. Дитина може ТОЛЬКО говорити, коли її просять говорити, і може ТІЛЬКИ діяти, коли вона отримала дозвіл.
З IoC:
Дитина тепер має можливість задавати питання, а батько може відповідати відповідями та дозволами. Просто означає, що управління перевернуто! Дитина тепер вільна задавати питання в будь-який час, і хоча існує ще залежність з батьком щодо дозволів, він не залежить від засобів говорити / задавати питання.
У технологічному способі пояснення це дуже схоже на взаємодію консолі / оболонки / cmd проти GUI. (Яка відповідь Марка Гаррісона вище № 2 верхньої відповіді). На консолі ви залежите від того, що вам запитують / показують, і ви не можете перейти до інших меню та функцій, не відповівши спочатку на це питання; дотримуючись суворого послідовного потоку. (програмно це як метод / цикл функцій). Однак із графічним інтерфейсом, меню та функції викладені, і користувач може вибирати все, що потрібно, тим самим маючи більше контролю та менше обмеження. (програмно, у меню є зворотний виклик, коли вибрано дію).
Інверсія управління стосується передачі контролю з бібліотеки клієнту. Це має більше сенсу, коли ми говоримо про клієнта, який вводить (передає) значення функції (лямбда-вираз) у функцію вищого порядку (бібліотечна функція), яка контролює (змінює) поведінку функції бібліотеки. Клієнт або структура, яка вводить залежність бібліотеки (яка несе поведінку), також може вважатися IoC
Оскільки відповідей на питання вже багато, але жоден з них не показує розбиття терміну управління інверсією, я бачу можливість дати більш коротку та корисну відповідь.
Інверсія управління - це схема, яка реалізує принцип інверсії залежності (DIP). DIP визначає наступне: 1. Модулі високого рівня не повинні залежати від модулів низького рівня. Обидва повинні залежати від абстракцій (наприклад, інтерфейсів). 2. Абстракції не повинні залежати від деталей. Деталі (конкретні реалізації) повинні залежати від абстракцій.
Існує три типи інверсії управління:
Постачальники інверсії інтерфейсу не повинні визначати інтерфейс. Натомість споживач повинен визначити інтерфейс, а постачальники повинні його реалізувати. Інверсія інтерфейсу дозволяє усунути необхідність змінювати споживача щоразу, коли додається новий постачальник.
Інверсія потоку Змінює контроль потоку. Наприклад, у вас є консольна програма, де ви попросили ввести багато параметрів, і після кожного введеного параметра ви змушені натискати Enter. Тут ви можете застосувати Flow Inversion і реалізувати настільний додаток, де користувач може вибрати послідовність введення параметрів, користувач може редагувати параметри, а на останньому кроці користувачеві потрібно натиснути Enter лише один раз.
Інверсія створення Це може бути реалізовано за такими шаблонами: Заводська модель, Локатор обслуговування та Введення залежностей. Інверсія створення допомагає усунути залежності між типами, що переміщують процес створення об'єктів залежності поза типом, який використовує ці об'єкти залежності. Чому залежності погані? Ось декілька прикладів: пряме створення нового об’єкта у вашому коді ускладнює тестування; неможливо змінити посилання в зборах без перекомпіляції (порушення принципу OCP); Ви не можете легко замінити інтерфейс робочого столу веб-інтерфейсом.
Отже номер 1 вище . Що таке інверсія управління?
Технічне обслуговування - це річ, яку вона вирішує для мене. Це гарантує, що я використовую інтерфейси, щоб два класи не були інтимними один з одним.
Використовуючи такий контейнер, як Castle Windsor, він ще краще вирішує проблеми з технічним обслуговуванням. Можливість замінити компонент, який переходить до бази даних, на той, який використовує стійкість на основі файлів без зміни рядка коду, дивовижний (зміна конфігурації, ви готові).
І як тільки ви потрапляєте в дженерики, він стає ще кращим. Уявіть, що у вас є видавець повідомлень, який приймає записи та публікує повідомлення. Не байдуже, що він публікує, але йому потрібен картограф, щоб взяти щось із запису до повідомлення.
public class MessagePublisher<RECORD,MESSAGE>
{
public MessagePublisher(IMapper<RECORD,MESSAGE> mapper,IRemoteEndpoint endPointToSendTo)
{
//setup
}
}
Я писав це колись, але тепер я можу вводити багато типів у цей набір кодів, якщо публікую різні типи повідомлень. Я також можу написати картографи, які беруть запис одного типу, і відображають їх у різні повідомлення. Використання DI з Generics дало мені можливість написати дуже мало коду для виконання багатьох завдань.
О так, є проблеми, пов'язані зі встановленням безпеки, але вони є вторинними щодо переваг IoC / DI.
Я, безумовно, люблю IoC / DI.
3. Це стає більш підходящим з тієї хвилини, коли у вас є проект середнього розміру дещо більшої складності. Я б сказав, що це стає доречним, як тільки ти починаєш відчувати біль.
Створення об'єкта в класі називається герметичним з'єднанням, Spring усуває цю залежність, слідуючи схемі проектування (DI / IOC). У якому об'єкт класу передається в конструктор, а не створюється в класі. Більше ми надаємо контрольну змінну суперкласу в конструкторі для визначення більш загальної структури.