Ответ
Внедрение зависимостей (Dependency Injection, DI) — это конкретный шаблон проектирования (паттерн) и техника реализации. Его суть в том, что зависимости объекта (сервисы, которые он использует) не создаются им самим, а предоставляются ему извне ("внедряются").
Инверсия зависимостей (Dependency Inversion Principle, DIP) — это один из пяти принципов SOLID, то есть более высокоуровневое правило проектирования гибких систем.
DIP состоит из двух утверждений:
- Модули верхнего уровня не должны зависеть от модулей нижнего уровня. Оба должны зависеть от абстракций.
- Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
Как DI помогает реализовать DIP: DI — это механизм, который позволяет легко следовать DIP, передавая зависимости через абстракции (интерфейсы).
Пример без принципов:
// Класс нижнего уровня (деталь)
class FileLogger {
public function log($message) {
file_put_contents('app.log', $message, FILE_APPEND);
}
}
// Класс верхнего уровня жёстко зависит от детали
class OrderService {
private $logger;
public function __construct() {
$this->logger = new FileLogger(); // Прямое создание зависимости
}
}
Пример с DIP и DI:
// 1. Абстракция (интерфейс), от которой будут зависять оба уровня
interface LoggerInterface {
public function log($message);
}
// 2. Деталь (модуль нижнего уровня) зависит от абстракции
class FileLogger implements LoggerInterface {
public function log($message) { /* ... */ }
}
class DatabaseLogger implements LoggerInterface {
public function log($message) { /* ... */ }
}
// 3. Модуль верхнего уровня зависит от абстракции, а не от детали
class OrderService {
private $logger;
// 4. Внедрение зависимости (DI) через конструктор
public function __construct(LoggerInterface $logger) {
$this->logger = $logger; // Получаем готовую реализацию
}
public function createOrder() {
// ... логика создания заказа
$this->logger->log('Order created');
}
}
// 5. Сборка зависимостей (например, в контейнере)
$logger = new DatabaseLogger(); // Легко заменить реализацию
$orderService = new OrderService($logger);
Итог:
- DIP — это цель/принцип: "Завись от абстракций".
- DI — это средство/способ: "Передавай зависимости извне". Используя DI для передачи абстракций, мы автоматически соблюдаем принцип инверсии зависимостей, получая слабосвязанный, тестируемый и гибкий код.