mirror of
https://github.com/DesignPatternsPHP/DesignPatternsPHP.git
synced 2025-06-02 20:19:04 +02:00
Added Service Locator pattern
This commit is contained in:
parent
c232381f3b
commit
67c26edeb3
8
ServiceLocator/DatabaseService.php
Normal file
8
ServiceLocator/DatabaseService.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\ServiceLocator;
|
||||
|
||||
class DatabaseService implements DatabaseServiceInterface
|
||||
{
|
||||
|
||||
}
|
8
ServiceLocator/DatabaseServiceInterface.php
Normal file
8
ServiceLocator/DatabaseServiceInterface.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\ServiceLocator;
|
||||
|
||||
interface DatabaseServiceInterface
|
||||
{
|
||||
|
||||
}
|
8
ServiceLocator/LogService.php
Normal file
8
ServiceLocator/LogService.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\ServiceLocator;
|
||||
|
||||
class LogService implements LogServiceInterface
|
||||
{
|
||||
|
||||
}
|
8
ServiceLocator/LogServiceInterface.php
Normal file
8
ServiceLocator/LogServiceInterface.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\ServiceLocator;
|
||||
|
||||
interface LogServiceInterface
|
||||
{
|
||||
|
||||
}
|
16
ServiceLocator/README.md
Normal file
16
ServiceLocator/README.md
Normal file
@ -0,0 +1,16 @@
|
||||
# Service Locator
|
||||
|
||||
## Purpose
|
||||
|
||||
To implement a loosely coupled architecture in order to get better testable, maintainable and extendable code.
|
||||
DI pattern and Service Locator pattern are an implementation of the Inverse of Control pattern.
|
||||
|
||||
## Usage
|
||||
|
||||
With `ServiceLocator` you can register a service for a given interface. By using the interface you can retrieve the service
|
||||
and use it in the classes of the application without knowing its implementation. You can configure and inject the
|
||||
Service Locator object on bootstrap.
|
||||
|
||||
## Examples
|
||||
|
||||
* Zend Framework 2 uses Service Locator to create and share services used in the framework(i.e. EventManager, ModuleManager, all custom user services provided by modules, etc...)
|
105
ServiceLocator/ServiceLocator.php
Normal file
105
ServiceLocator/ServiceLocator.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\ServiceLocator;
|
||||
|
||||
class ServiceLocator implements ServiceLocatorInterface
|
||||
{
|
||||
/**
|
||||
* All services.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $services;
|
||||
|
||||
/**
|
||||
* The services which have an instance.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $instantiated;
|
||||
|
||||
/**
|
||||
* True if a service can be shared.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $shared;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->services = array();
|
||||
$this->instantiated = array();
|
||||
$this->shared = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a service with specific interface.
|
||||
*
|
||||
* @param string $interface
|
||||
* @param string|object $service
|
||||
* @param bool $share
|
||||
*/
|
||||
public function add($interface, $service, $share = true)
|
||||
{
|
||||
/**
|
||||
* When you add a service, you should register it
|
||||
* with its interface or with a string that you can use
|
||||
* in the future even if you will change the service implementation.
|
||||
*/
|
||||
|
||||
if(is_object($service) && $share)
|
||||
$this->instantiated[$interface] = $service;
|
||||
|
||||
$this->services[$interface] = (is_object($service) ? get_class($service) : $service);
|
||||
$this->shared[$interface] = $share;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a service is registered.
|
||||
*
|
||||
* @param string $interface
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has($interface)
|
||||
{
|
||||
return (isset($this->services[$interface]) || isset($this->instantiated[$interface]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the service registered for the interface.
|
||||
*
|
||||
* @param string $interface
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($interface)
|
||||
{
|
||||
// Retrieves the instance if it exists and it is shared
|
||||
if(isset($this->instantiated[$interface]) && $this->shared[$interface])
|
||||
return $this->instantiated[$interface];
|
||||
|
||||
// otherwise gets the service registered.
|
||||
$service = $this->services[$interface];
|
||||
|
||||
// You should check if the service class exists and
|
||||
// the class is instantiable.
|
||||
|
||||
// This example is a simple implementation, but
|
||||
// when you create a service, you can decide
|
||||
// if $service is a factory or a class.
|
||||
// By registering a factory you can create your services
|
||||
// using the DependencyInjection pattern.
|
||||
|
||||
// ...
|
||||
|
||||
// Creates the service object
|
||||
$object = new $service();
|
||||
|
||||
// and saves it if the service must be shared.
|
||||
if($this->shared[$interface])
|
||||
$this->instantiated[$interface] = $object;
|
||||
|
||||
return $object;
|
||||
}
|
||||
}
|
24
ServiceLocator/ServiceLocatorInterface.php
Normal file
24
ServiceLocator/ServiceLocatorInterface.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\ServiceLocator;
|
||||
|
||||
interface ServiceLocatorInterface
|
||||
{
|
||||
/**
|
||||
* Checks if a service is registered.
|
||||
*
|
||||
* @param string $interface
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has($interface);
|
||||
|
||||
/**
|
||||
* Gets the service registered for the interface.
|
||||
*
|
||||
* @param string $interface
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($interface);
|
||||
}
|
102
Tests/ServiceLocator/ServiceLocatorTest.php
Normal file
102
Tests/ServiceLocator/ServiceLocatorTest.php
Normal file
@ -0,0 +1,102 @@
|
||||
<?php
|
||||
/**
|
||||
* DesignPatternsPHP
|
||||
*
|
||||
* Copyright (c) 2014 Matteo Tafani Alunno
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace DesignPatterns\Tests\ServiceLocator;
|
||||
|
||||
use DesignPatterns\ServiceLocator\DatabaseService;
|
||||
use DesignPatterns\ServiceLocator\LogService;
|
||||
use DesignPatterns\ServiceLocator\ServiceLocator;
|
||||
use \PHPUnit_Framework_TestCase as TestCase;
|
||||
|
||||
class ServiceLocatorTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var LogService
|
||||
*/
|
||||
private $logService;
|
||||
|
||||
/**
|
||||
* @var DatabaseService
|
||||
*/
|
||||
private $databaseService;
|
||||
|
||||
/**
|
||||
* @var ServiceLocator
|
||||
*/
|
||||
private $serviceLocator;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->serviceLocator = new ServiceLocator();
|
||||
|
||||
$this->logService = new LogService();
|
||||
$this->databaseService = new DatabaseService();
|
||||
}
|
||||
|
||||
public function testHasServices()
|
||||
{
|
||||
$this->serviceLocator->add('DesignPatterns\ServiceLocator\LogServiceInterface', $this->logService);
|
||||
$this->serviceLocator->add('DesignPatterns\ServiceLocator\DatabaseServiceInterface', $this->databaseService);
|
||||
|
||||
$this->assertTrue($this->serviceLocator->has('DesignPatterns\ServiceLocator\LogServiceInterface'));
|
||||
$this->assertTrue($this->serviceLocator->has('DesignPatterns\ServiceLocator\DatabaseServiceInterface'));
|
||||
|
||||
$this->assertFalse($this->serviceLocator->has('DesignPatterns\ServiceLocator\FakeServiceInterface'));
|
||||
}
|
||||
|
||||
public function testServicesWithObject()
|
||||
{
|
||||
$this->serviceLocator->add('DesignPatterns\ServiceLocator\LogServiceInterface', $this->logService);
|
||||
$this->serviceLocator->add('DesignPatterns\ServiceLocator\DatabaseServiceInterface', $this->databaseService);
|
||||
|
||||
$this->assertSame($this->logService, $this->serviceLocator->get('DesignPatterns\ServiceLocator\LogServiceInterface'));
|
||||
$this->assertSame($this->databaseService, $this->serviceLocator->get('DesignPatterns\ServiceLocator\DatabaseServiceInterface'));
|
||||
}
|
||||
|
||||
public function testServicesWithClass()
|
||||
{
|
||||
$this->serviceLocator->add('DesignPatterns\ServiceLocator\LogServiceInterface', get_class($this->logService));
|
||||
$this->serviceLocator->add('DesignPatterns\ServiceLocator\DatabaseServiceInterface', get_class($this->databaseService));
|
||||
|
||||
$this->assertNotSame($this->logService, $this->serviceLocator->get('DesignPatterns\ServiceLocator\LogServiceInterface'));
|
||||
$this->assertInstanceOf('DesignPatterns\ServiceLocator\LogServiceInterface', $this->serviceLocator->get('DesignPatterns\ServiceLocator\LogServiceInterface'));
|
||||
|
||||
$this->assertNotSame($this->databaseService, $this->serviceLocator->get('DesignPatterns\ServiceLocator\DatabaseServiceInterface'));
|
||||
$this->assertInstanceOf('DesignPatterns\ServiceLocator\DatabaseServiceInterface', $this->serviceLocator->get('DesignPatterns\ServiceLocator\DatabaseServiceInterface'));
|
||||
}
|
||||
|
||||
public function testServicesNotShared()
|
||||
{
|
||||
$this->serviceLocator->add('DesignPatterns\ServiceLocator\LogServiceInterface', $this->logService, false);
|
||||
$this->serviceLocator->add('DesignPatterns\ServiceLocator\DatabaseServiceInterface', $this->databaseService, false);
|
||||
|
||||
$this->assertNotSame($this->logService, $this->serviceLocator->get('DesignPatterns\ServiceLocator\LogServiceInterface'));
|
||||
$this->assertInstanceOf('DesignPatterns\ServiceLocator\LogServiceInterface', $this->serviceLocator->get('DesignPatterns\ServiceLocator\LogServiceInterface'));
|
||||
|
||||
$this->assertNotSame($this->databaseService, $this->serviceLocator->get('DesignPatterns\ServiceLocator\DatabaseServiceInterface'));
|
||||
$this->assertInstanceOf('DesignPatterns\ServiceLocator\DatabaseServiceInterface', $this->serviceLocator->get('DesignPatterns\ServiceLocator\DatabaseServiceInterface'));
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user