← Назад к вопросам
Что такое dependency inversion principle?
1.0 Junior🔥 231 комментариев
#SOLID и паттерны проектирования
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Dependency Inversion Principle (DIP)
Dependency Inversion Principle — один из пяти SOLID принципов, сформулированный Робертом Мартином. Этот принцип говорит, что высокоуровневые модули не должны зависеть от низкоуровневых модулей. Оба должны зависеть от абстракций. Кроме того, абстракции не должны зависеть от деталей, а детали должны зависеть от абстракций.
Проблема без DIP
Представь, что у тебя есть сервис доставки, который напрямую зависит от конкретной реализации:
public class DeliveryService {
private EmailNotifier emailNotifier = new EmailNotifier();
private SmsNotifier smsNotifier = new SmsNotifier();
public void notifyCustomer(Order order) {
emailNotifier.send(order.getCustomerEmail());
smsNotifier.send(order.getCustomerPhone());
}
}
Проблемы:
DeliveryServiceжёстко привязан к конкретным классамEmailNotifierиSmsNotifier- Сложно тестировать (нельзя подменить реальные сервисы)
- Сложно добавить новый способ уведомления (например, Telegram)
- Изменение в
EmailNotifierможет сломатьDeliveryService
Решение с DIP
Мы вводим абстракцию (интерфейс) и зависим от неё:
public interface Notifier {
void send(String recipient);
}
public class EmailNotifier implements Notifier {
@Override
public void send(String email) {
// отправка email
}
}
public class SmsNotifier implements Notifier {
@Override
public void send(String phone) {
// отправка SMS
}
}
public class DeliveryService {
private List<Notifier> notifiers;
// Инъекция зависимостей через конструктор
public DeliveryService(List<Notifier> notifiers) {
this.notifiers = notifiers;
}
public void notifyCustomer(Order order) {
for (Notifier notifier : notifiers) {
notifier.send(order.getCustomerInfo());
}
}
}
Преимущества DIP
- Слабая связанность —
DeliveryServiceзависит от интерфейса, а не от конкретных классов - Лёгче тестировать — можно создать Mock-реализацию
Notifier - Легче расширять — добавить
TelegramNotifierбез измененияDeliveryService - Гибкость конфигурации — в runtime можно выбрать, какие notifiers использовать
Пример с тестированием
@Test
public void testCustomerNotification() {
// Mock-реализация
Notifier mockNotifier = new Notifier() {
@Override
public void send(String recipient) {
// Проверяем, что метод вызвался
}
};
DeliveryService service = new DeliveryService(Arrays.asList(mockNotifier));
Order order = new Order("customer@email.com");
service.notifyCustomer(order); // Работает с mock
}
Правильный вектор зависимостей
Вместо:
DeliveryService → EmailNotifier → SMTP
→ SmsNotifier → SMS API
Мы получаем:
DeliveryService → Notifier (интерфейс)
↑
EmailNotifier, SmsNotifier (реализации зависят от интерфейса)
Связь с другими SOLID принципами
- S (Single Responsibility) — каждый Notifier имеет одну ответственность
- O (Open/Closed) — система открыта для новых реализаций (новых Notifier)
- L (Liskov Substitution) — любая реализация Notifier заменяема
- I (Interface Segregation) — интерфейс Notifier минимален и сфокусирован
DIP — это фундамент архитектуры, позволяющий создавать гибкие, тестируемые и поддерживаемые системы.