Какие принципы SOLID нарушает паттерн Service Locator?

«Какие принципы SOLID нарушает паттерн Service Locator?» — вопрос из категории Архитектура, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Паттерн Service Locator, при котором класс явно запрашивает зависимости из глобального реестра, нарушает два ключевых принципа SOLID:

1. Принцип инверсии зависимостей (D — Dependency Inversion Principle): Это главное нарушение. Вместо того чтобы зависимости предоставлялись классу извне (через конструктор или сеттер), класс сам знает о конкретном механизме их получения (сервис-локаторе). Это создаёт скрытую зависимость от глобального состояния.

2. Принцип единственной ответственности (S — Single Responsibility Principle): Класс начинает нести дополнительную ответственность — знание о том, как и где найти свои зависимости, что усложняет его логику.

Сравнение на примере:

// Нарушение DIP и SRP с Service Locator
class OrderProcessor {
    private $mailer;
    private $logger;

    public function __construct() {
        // Класс знает о конкретной реализации локатора
        $this->mailer = ServiceLocator::get(MailService::class);
        $this->logger = ServiceLocator::get(LoggerInterface::class);
    }

    public function process(Order $order) {
        // ... логика
        $this->mailer->sendReceipt($order);
    }
}
// Тестирование сложно — нужно настроить глобальный ServiceLocator.

// Соблюдение SOLID с внедрением зависимостей (Dependency Injection)
class OrderProcessor {
    public function __construct(
        private MailServiceInterface $mailer,
        private LoggerInterface $logger
    ) {}

    public function process(Order $order) {
        // ... логика
        $this->mailer->sendReceipt($order);
    }
}
// Зависимости явны. Тестирование простое — можно передать моки.
$processor = new OrderProcessor(new MockMailer(), new NullLogger());

Service Locator создаёт неявные связи, затрудняет понимание зависимостей класса и его модульное тестирование, поэтому в современной разработке предпочтение отдаётся явному внедрению зависимостей (Dependency Injection).