ependency Inversion Principle
Классы верхних уровней не должны зависеть от классов нижних уровней. Оба должны зависеть от абстракций. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
Обычно, при проектировании программ можно выделить два уровня классов.
- Классы нижнего уровня реализуют базовые операции вроде работы с диском, передачи данных по сети, подключению к базе данных и прочее.
- Классы высокого уровня содержат сложную бизнес-логику программы, которая опирается на классы низкого уровня для осуществления более простых операций.
Зачастую, вы сперва проектируете классы нижнего уровня, а только потом берётесь за верхний уровень. При таком подходе классы бизнес-логики становятся зависимыми от более примитивных низкоуровневых классов. Каждое изменения в низкоуровневом классе может затронуть классы бизнес-логики, которые его используют.
Принцип инверсии зависимостей предлагает изменить направление, в котором происходит проектирование.
- Для начала вам нужно описать интерфейс низкоуровневых операций, которые нужны классу бизнес-логики.
- Это позволит вам убрать зависимость класса бизнес-логики от конкретного низкоуровневого класса, заменив её «мягкой» зависимостью от интерфейса.
- Низкоуровневый класс, в свою очередь, станет зависимый от интерфейса, определённого бизнес-логикой.
Принцип инверсии зависимостей часто идёт в ногу с принципом открытости/закрытости: вы сможете расширять низкоуровневые классы и использовать их вместе с классами бизнес-логики, не изменяя код последних.
Пример
В этом примере высокоуровневый класс формирования бюджетных отчётов напрямую использует класс базы данных для загрузки и сохранения своей информации.

ДО: высокоуровневый класс зависит от низкоуровневого.
Вы можете исправить проблему, создав высокоуровневый интерфейс для загрузки/сохранения данных и привязать к нему класс отчётов. Низкоуровневые классы должны реализовать этот интерфейс, чтобы их объекты можно было использовать внутри объекта отчётов.

ПОСЛЕ: низкоуровневые классы зависят от высокоуровневой абстракции.
Таким образом, меняется направление зависимости. Если раньше высокий уровень зависел от низкого, то сейчас всё наоборот — низкоуровневые классы зависят от высокоуровневого интерфейса.

