Ответ
Внедрение зависимостей (DI) — это паттерн проектирования, при котором зависимости объекта (сервисы, которые он использует) предоставляются ему извне, а не создаются внутри самого объекта. Это реализация принципа инверсии зависимостей (Dependency Inversion Principle, DIP).
Основные цели и преимущества:
- Снижение связанности (Loose Coupling): Класс не зависит от конкретной реализации своей зависимости, а только от её абстракции (интерфейса).
- Упрощение тестирования: В юнит-тесты легко подставлять заглушки (mocks) или стабы (stubs) через конструктор или сеттер.
- Гибкость и поддерживаемость: Реализацию зависимости можно изменить в одном месте (конфигурации контейнера), не правя код всех использующих её классов.
- Централизованное управление жизненным циклом: Контейнер DI (как Spring) управляет созданием и связыванием объектов.
Пример:
// 1. Высокоуровненый модуль зависит от абстракции (интерфейса)
interface NotificationService {
void send(String message);
}
// 2. Конкретная реализация
class EmailService implements NotificationService {
public void send(String message) { /* ... */ }
}
// 3. Класс, который использует сервис. Зависимость ВНЕДРЯЕТСЯ извне.
class OrderProcessor {
private final NotificationService notifier;
// Внедрение через конструктор (предпочтительный способ)
public OrderProcessor(NotificationService notifier) {
this.notifier = notifier; // Зависимость предоставлена
}
public void processOrder(Order order) {
// ... логика обработки
notifier.send("Order processed"); // Использование абстракции
}
}
// 4. Конфигурация (например, в Spring)
@Configuration
public class AppConfig {
@Bean
public NotificationService notificationService() {
return new EmailService(); // Здесь определяется конкретная реализация
}
@Bean
public OrderProcessor orderProcessor(NotificationService service) {
return new OrderProcessor(service); // Контейнер Spring сам внедрит зависимость
}
}