Skip to main content

Які існують типи впровадження залежностей?

Існує три основні типи впровадження залежностей (Dependency Injection) - за способом, як об'єкт отримує свої залежності:


1. Constructor Injection (впровадження через конструктор)

Найнадійніший і найпопулярніший спосіб. Залежність передається при створенні об'єкта через конструктор.

java
class UserService { private final Database db; public UserService(Database db) { // впровадження this.db = db; } }

Особливості:

  • Всі обов'язкові залежності задаються одразу.
  • Об'єкт не можна створити без них - отже, він завжди в коректному стані.
  • Чудово підходить для immutable класів.
  • Спрощує тестування - можна підставити mock при створенні.

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


2. Setter Injection (впровадження через сеттери / методи)

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

java
class UserService { private Database db; public void setDatabase(Database db) { // впровадження this.db = db; } }

Особливості:

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

Плюси: гнучкість, можливість пізнього зв'язування. Мінуси: об'єкт можна створити в "неповному" стані; більше ризиків помилок.


3. Field Injection (впровадження через поля)

Контейнер напряму встановлює залежність у поле класу, минаючи конструктор. (Популярно в Spring, Android та ін.)

java
class UserService { @Autowired private Database db; // впровадження }

Особливості:

  • Найкоротший синтаксис - нічого не потрібно писати вручну.
  • Підходить для швидкої розробки і простих класів.

Плюси: мінімум коду, простота. Мінуси:

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

4. (Іноді виділяють ще)

Interface Injection - рідкісний варіант, коли контейнер викликає метод інтерфейсу, передаючи залежність:

java
interface DatabaseAware { void setDatabase(Database db); }

Контейнер знаходить реалізацію інтерфейсу і сам викликає setDatabase().


Зведена таблиця

Тип DIЯк впроваджуєтьсяКоли використовуватиПлюсиМінуси
ConstructorЧерез конструкторОсновні залежностіБезпека, тестованістьБагато параметрів
SetterЧерез методиНеобов'язкові залежностіГнучкістьМожлива неповна ініціалізація
FieldЧерез поляШвидке налаштування, прості класиМінімум кодуЗалежність прихована, погано тестується
InterfaceЧерез метод інтерфейсуСпеціальні фреймворкиГнучкістьМайже не використовується

Висновок:

У реальних проектах зазвичай комбінують constructor injection (для обов'язкових залежностей) і setter injection (для опціональних). Field injection застосовують там, де важлива стислість, але не сувора модульність.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.