====== 4.1. Локатор Служб (Service Locator)====== **Этот шаблон считается анти-паттерном!** Некоторые считают Локатор Служб анти-паттерном. Он нарушает принцип инверсии зависимостей ([[https://ru.wikipedia.org/wiki/Принцип_инверсии_зависимостей|Dependency Inversion principle]]) из набора принципов [[https://ru.wikipedia.org/wiki/SOLID|SOLID]]. Локатор Служб скрывает зависимости данного класса вместо их совместного использования, как в случае шаблона Внедрение Зависимости ([[https://ru.wikipedia.org/wiki/Внедрение_зависимости|Dependency Injection]]). В случае изменения данных зависимостей мы рискуем сломать функционал классов, которые их используют, вследствие чего затрудняется поддержка системы. ===== 4.1.1. Назначение===== Для реализации слабосвязанной архитектуры, чтобы получить хорошо тестируемый, сопровождаемый и расширяемый код. Паттерн Инъекция зависимостей (DI) и паттерн Локатор Служб — это реализация паттерна Инверсия управления (Inversion of Control, IoC). ===== 4.1.2. Использование===== С ''Локатором Служб'' вы можете зарегистрировать сервис для определенного интерфейса. С помощью интерфейса вы можете получить зарегистрированный сервис и использовать его в классах приложения, не зная его реализацию. Вы можете настроить и внедрить объект Service Locator на начальном этапе сборки приложения. ===== 4.1.3. Диаграмма UM ===== {{:php:shablony_proektirovanija:additionally:121wqsd.png |}} }===== 4.1.4. Код ===== Вы можете найти этот код на [[https://github.com/domnikl/DesignPatternsPHP/tree/main/More/ServiceLocator|GitHub]] Service.php ServiceLocator.php instantiated[$class] = $service; } public function addClass(string $class, array $params) { $this->services[$class] = $params; } public function has(string $interface): bool { return isset($this->services[$interface]) || isset($this->instantiated[$interface]); } public function get(string $class): Service { if (isset($this->instantiated[$class])) { return $this->instantiated[$class]; } $object = new $class(...$this->services[$class]); if (!$object instanceof Service) { throw new InvalidArgumentException('Could not register service: is no instance of Service'); } $this->instantiated[$class] = $object; return $object; } } LogService.php ===== 4.1.5. Тест===== Tests/ServiceLocatorTest.php serviceLocator = new ServiceLocator(); } public function testHasServices() { $this->serviceLocator->addInstance(LogService::class, new LogService()); $this->assertTrue($this->serviceLocator->has(LogService::class)); $this->assertFalse($this->serviceLocator->has(self::class)); } public function testGetWillInstantiateLogServiceIfNoInstanceHasBeenCreatedYet() { $this->serviceLocator->addClass(LogService::class, []); $logger = $this->serviceLocator->get(LogService::class); $this->assertInstanceOf(LogService::class, $logger); } }