Dependency Injection: внедрение зависимостей в программировании
Dependency Injection (DI) является практикой разработки, которая помогает управлять объектами и их зависимостями в приложении. Она позволяет убрать жесткие связи между компонентами и обезопасить программу от изменений в конкретных классах. Реализуется она путем внедрения (инъекции) зависимостей в классы извне, а не внутри классов.
Рассмотрим на примере. Представим себе класс покупателя:
class Customer {
private ShoppingList shoppingList;
public Customer() {
shoppingList = new ShoppingList();
}
public void buyGoods() {
for (Goods good : shoppingList.getGoods()) {
good.buy();
}
}
}
В этом примере мы видим, что класс Customer зависит от объекта ShoppingList. Это может быть неудобно, видимость нашего кода может окажется трудно обслуживаемой, кроме этого будет сложно провести тестирование и перенести проект на новую версию фреймворка. Так нельзя и поэтому нам нужно ослабить жесткую зависимость.
Используя DI мы можем внедрить зависимость в конструктор класса:
class Customer {
private ShoppingList shoppingList;
public Customer(ShoppingList shoppingList) {
this.shoppingList = shoppingList;
}
public void buyGoods() {
for (Goods good : shoppingList.getGoods()) {
good.buy();
}
}
}
Теперь в нашем классе Customer присутствует зависимость в виде объекта ShoppingList, который мы передаем в конструктор при создании объекта.
В итоге, мы достигли более гибкой архитектуры, потому что можно подставлять любой объект ShoppingList, в зависимости от необходимых требований.
Существует множество инструментов для реализации DI в Java, таких как Spring, Guice, Dagger и др. Ниже приведен пример реализации DI с помощью Spring:
@Service
public class CustomerService {
private final ShoppingList shoppingList;
@Autowired
public CustomerService(ShoppingList shoppingList) {
this.shoppingList = shoppingList;
}
public void buyGoods() {
for (Goods good : shoppingList.getGoods()) {
good.buy();
}
}
}
И с помощью простого Java-кода:
public class CustomerApplication {
public static void main(String[] args) {
ShoppingList shoppingList = new ShoppingList();
Customer customer = new Customer(shoppingList);
customer.buyGoods();
}
}
В обоих случаях мы можем изменять классы ShoppingList без изменения кода CustomerService и CustomerApplication. DI позволяет добиваться максимальной гибкости и эффективности в написании кода.