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