Ответ
Принцип инверсии зависимостей (DIP) — пятый принцип SOLID. Он декларирует:
- Модули верхнего уровня не должны зависеть от модулей нижнего уровня. Оба должны зависеть от абстракций.
- Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
Цель — уменьшить связанность между компонентами, сделав систему более гибкой, расширяемой и удобной для тестирования.
Пример нарушения DIP в C++:
// Модуль нижнего уровня (деталь)
class SqlDatabase {
public:
void saveData(const std::string& data) { /* ... */ }
};
// Модуль верхнего уровня жёстко зависит от детали
class ReportService {
SqlDatabase db; // Прямая зависимость от конкретного класса
public:
void generateReport() {
// ... логика отчёта
db.saveData(reportData);
}
};
Здесь ReportService тесно связан с SqlDatabase. Замена базы данных потребует изменений в ReportService.
Пример с применением DIP:
// Абстракция (интерфейс)
class IDataStorage {
public:
virtual ~IDataStorage() = default;
virtual void save(const std::string& data) = 0;
};
// Модуль нижнего уровня зависит от абстракции
class SqlDatabase : public IDataStorage {
public:
void save(const std::string& data) override { /* ... */ }
};
class FileStorage : public IDataStorage {
public:
void save(const std::string& data) override { /* ... */ }
};
// Модуль верхнего уровня также зависит от абстракции
class ReportService {
IDataStorage& storage; // Зависимость от интерфейса
public:
ReportService(IDataStorage& s) : storage(s) {} // Внедрение зависимости
void generateReport() {
// ... логика отчёта
storage.save(reportData);
}
};
Теперь ReportService не знает о деталях хранения данных. Мы можем легко подменить реализацию IDataStorage (для тестирования, смены БД и т.д.), не меняя код сервиса.
Видео-ответы
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶