Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
opi.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
1.81 Mб
Скачать

Тема 6. Створення слабо зв'язаних компонентів. Впровадження залежності.

Як вже було сказано, одна з найбільш важливих особливостей моделі MVC полягає в тому, що вона робить можливим поділ відповідальності. Нам потрібно, щоб компоненти в нашому додатку були максимально незалежними один від одного і мали лише таку кількість взаємозалежностей, яким ми зможемо управляти.

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

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

Тоді будь-який інший компонент нашого застосування, якому потрібно надіслати повідомлення електронної пошти – наприклад, допоміжний метод скидання пароля PasswordResetHelper – може відправити повідомлення, звертаючись тільки до методів, певним всередині інтерфейсу. Як видно з рисунку 1, ніякої прямої залежності між PasswordResetHelper і MyEmailSender не існує.

Рис. 1 - Використання інтерфейсів для роз'єднання компонентів

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

На замітку! Не всі відношення обов'язково розривати за допомогою інтерфейсу. У дійсності рішення залежить від ступеня складності застосування, виду необхідного тестування і і простому додатку ASP.NET MVC можна було б відмовитися від розриву зв'язку між контролерами і моделлю предметної області .

Інтерфейси допомагають роз'єднати компоненти, але ми як і раніше стикаємося з проблемою – C# не надає вбудованого способу простого створення об'єктів, які реалізують інтерфейси. Єдине, що ми можемо зробити – це створити екземпляр конкретного компонента. У результаті ми отримуємо код, наведений у лістингу 1.

Лістинг 1. Створення примірників конкретних класів для отримання реалізації інтерфейсу

public class PasswordResetHelper {

public void ResetFasswordO {

IEmailSender mySender = new MyEmailSender () ;

// ... call interface methods to configure e-mail details.

mySender . SendEmail ();

}

}

Ми знаходимося лише на середині шляху до створення слабко зв'язаних компонентів. Клас PasswordResetHelper конфігурує і відправляє повідомлення електронної пошти за допомогою інтерфейсу IEmailSender, але щоб створити об’єкт, який реалізує цей інтерфейс, йому потрібно створити екземпляр MyEmailSender.

Ми посилили ситуацію. Тепер PasswordResetHelper залежить і від IEmailSender, і від MyEmailSender. як показано на рисунку 2.

Рис. 2 - У кінцевому рахунку , компоненти виявляються тісно пов'язаними

Нам потрібно спосіб отримання об'єктів, які реалізують даний інтерфейс без необхідності безпосереднього створення реалізує об'єкта. Вирішення цієї проблеми називають впровадженням залежності (dependency injection - DI) або оберненням (інверсією) управління (inversion of control - IoC).

DI – це модель розробки, яка доповнює слабкий зв'язок, який ми почали створювати з додавання інтерфейсу IEmailSender у наш простий приклад. Вона є центральною концепцією для ефективної розробки додатків MVC.

Модель DI складається з двох частин. Для початку зі свого компонента – у даному випадку PasswordResetHelper – ми видаляємо будь-які залежності від конкретних класів. Це виконується за рахунок передачі реалізації необхідних інтерфейсів конструктору класу, як показано в лістингу 2.

Лістинг 2. Видалення залежностей із класу PasswordResetHelper

public class PasswordResetHelper

{

private IEmailSender emailSender;

public PasswordResetHelper (IEmailSender emailSenderParam)

{

emailSender = emailSenderParam;

}

public void ResetPasswordO

{

emailSender.SendEmail () ;

}

}

Ми розірвали залежність між PasswordResetHelper і MyEmailSender.

Конструктор PasswordResetHelper вимагає об'єкт, який реалізує інтерфейс IEmailSender, але не знає і не турбується про те, що собою являє цей об'єкт, і більше не відповідає за його створення.

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

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

Підхід, за якого залежності класу впроваджуються за допомогою загальнодоступної властивості називають впровадженням за допомогою установника .

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]