Ответ
Принцип инверсии зависимостей (DIP) — один из пяти принципов SOLID. Он утверждает, что:
- Модули верхнего уровня не должны зависеть от модулей нижнего уровня. Оба должны зависеть от абстракций.
- Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
Проблема без DIP: Класс верхнего уровня жёстко зависит от конкретной реализации нижнего уровня, что усложняет тестирование и замену компонентов.
// Конкретный класс нижнего уровня
class MySQLDatabase {
public void save(String data) { /* сохранение в MySQL */ }
}
// Класс верхнего уровня жёстко зависит от конкретной реализации
class Service {
private MySQLDatabase db = new MySQLDatabase(); // Прямая зависимость
public void process() {
db.save("data");
}
}
Решение с DIP: Зависимость инвертируется через введение абстракции (интерфейса) и внедрение зависимости (Dependency Injection).
// Абстракция (интерфейс)
interface Database {
void save(String data);
}
// Конкретная реализация зависит от абстракции
class MySQLDatabase implements Database {
@Override
public void save(String data) { /* сохранение в MySQL */ }
}
// Класс верхнего уровня зависит только от абстракции
class Service {
private Database db;
// Зависимость внедряется извне (через конструктор)
public Service(Database db) {
this.db = db;
}
public void process() {
db.save("data");
}
}
Преимущества:
- Снижение связанности: Классы зависят от стабильных абстракций, а не от изменчивых деталей.
- Упрощение тестирования: Легко подменить реальную реализацию мок-объектом в unit-тестах.
- Гибкость и расширяемость: Добавление новой реализации (например,
PostgresDatabase) не требует изменений в классеService.