Оглавление:
Карта сайта:
Оглавление:
Карта сайта:
Это старая версия документа!
Этот шаблон считается анти-паттерном!
Некоторые считают Локатор Служб анти-паттерном. Он нарушает принцип инверсии зависимостей (Dependency Inversion principle) из набора принципов SOLID. Локатор Служб скрывает зависимости данного класса вместо их совместного использования, как в случае шаблона Внедрение Зависимости (Dependency Injection). В случае изменения данных зависимостей мы рискуем сломать функционал классов, которые их используют, вследствие чего затрудняется поддержка системы.
Для реализации слабосвязанной архитектуры, чтобы получить хорошо тестируемый, сопровождаемый и расширяемый код. Паттерн Инъекция зависимостей (DI) и паттерн Локатор Служб — это реализация паттерна Инверсия управления (Inversion of Control, IoC).
С Локатором Служб вы можете зарегистрировать сервис для определенного интерфейса. С помощью интерфейса вы можете получить зарегистрированный сервис и использовать его в классах приложения, не зная его реализацию. Вы можете настроить и внедрить объект Service Locator на начальном этапе сборки приложения.
Вы можете найти этот код на GitHub
Service.php
1<?php 2 3namespace DesignPatterns\More\ServiceLocator; 4 5interface Service 6{ 7 8}
ServiceLocator.php
1<?php 2 3declare(strict_types=1); 4 5namespace DesignPatterns\More\ServiceLocator; 6 7use OutOfRangeException; 8use InvalidArgumentException; 9 10class ServiceLocator 11{ 12 /** 13 * @var string[][] 14 */ 15 private array $services = []; 16 17 /** 18 * @var Service[] 19 */ 20 private array $instantiated = []; 21 22 public function addInstance(string $class, Service $service) 23 { 24 $this->instantiated[$class] = $service; 25 } 26 27 public function addClass(string $class, array $params) 28 { 29 $this->services[$class] = $params; 30 } 31 32 public function has(string $interface): bool 33 { 34 return isset($this->services[$interface]) || isset($this->instantiated[$interface]); 35 } 36 37 public function get(string $class): Service 38 { 39 if (isset($this->instantiated[$class])) { 40 return $this->instantiated[$class]; 41 } 42 43 $object = new $class(...$this->services[$class]); 44 45 if (!$object instanceof Service) { 46 throw new InvalidArgumentException('Could not register service: is no instance of Service'); 47 } 48 49 $this->instantiated[$class] = $object; 50 51 return $object; 52 } 53}
LogService.php
1<?php 2 3declare(strict_types=1); 4 5namespace DesignPatterns\More\ServiceLocator; 6 7class LogService implements Service 8{ 9 10}
Tests/ServiceLocatorTest.php
1<?php 2 3declare(strict_types=1); 4 5namespace DesignPatterns\More\ServiceLocator\Tests; 6 7use DesignPatterns\More\ServiceLocator\LogService; 8use DesignPatterns\More\ServiceLocator\ServiceLocator; 9use PHPUnit\Framework\TestCase; 10 11class ServiceLocatorTest extends TestCase 12{ 13 private ServiceLocator $serviceLocator; 14 15 public function setUp(): void 16 { 17 $this->serviceLocator = new ServiceLocator(); 18 } 19 20 public function testHasServices() 21 { 22 $this->serviceLocator->addInstance(LogService::class, new LogService()); 23 24 $this->assertTrue($this->serviceLocator->has(LogService::class)); 25 $this->assertFalse($this->serviceLocator->has(self::class)); 26 } 27 28 public function testGetWillInstantiateLogServiceIfNoInstanceHasBeenCreatedYet() 29 { 30 $this->serviceLocator->addClass(LogService::class, []); 31 $logger = $this->serviceLocator->get(LogService::class); 32 33 $this->assertInstanceOf(LogService::class, $logger); 34 } 35}