Как ответить
Dependency Injection (DI) — это техника, при которой объект получает свои зависимости извне, а не создаёт их сам. Это частный случай инверсии управления (IoC). Основная цель — уменьшить связанность кода и упростить тестирование. Если класс сам создаёт свои зависимости, его сложно тестировать изолированно и сложно переиспользовать с другими реализациями.
Представим класс OrderService, который для сохранения заказа использует Database. Без DI он выглядит так:
public class OrderService {
private Database db = new MySQLDatabase();
public void save(Order order) {
db.save(order);
}
}С DI зависимости передаются конструктором:
public class OrderService {
private final Database db;
public OrderService(Database db) {
this.db = db;
}
public void save(Order order) {
db.save(order);
}
}Теперь мы можем подсунуть в тестах заглушку вместо реальной базы данных. Есть три основных способа внедрения:
- Через конструктор — самый распространённый, обязательные зависимости.
- Через сеттер — для опциональных зависимостей или когда нужно менять их в рантайме.
- Через интерфейс (метод) — реже, для ситуации, когда зависимость нужна только в одном методе.
В реальных проектах DI редко делают руками — используют IoC-контейнеры, например Spring (Java), Guice, Dagger (Android), Unity (C#). Контейнер автоматически резолвит цепочку зависимостей. В Spring это выглядит так:
@Service
public class OrderService {
private final Database db;
public OrderService(Database db) {
this.db = db;
}
}
@Configuration
public class AppConfig {
@Bean
public Database database() {
return new PostgreSQLDatabase();
}
}Контейнер сам создаёт Database и передаёт её в OrderService. При этом важно не злоупотреблять DI: если проект маленький или зависимости редко меняются, DI может добавить лишнюю сложность. Также DI полезен не только для тестов — он упрощает замену реализации (например, переключение с MySQL на PostgreSQL без изменения бизнес-логики).