start a restructure

This commit is contained in:
Antonio Spinelli
2014-03-21 18:03:44 -03:00
parent b0b0d4a1a4
commit e59d70a0ac
180 changed files with 21 additions and 16 deletions

View File

@@ -0,0 +1,8 @@
<?php
namespace DesignPatterns\ServiceLocator;
class DatabaseService implements DatabaseServiceInterface
{
}

View File

@@ -0,0 +1,8 @@
<?php
namespace DesignPatterns\ServiceLocator;
interface DatabaseServiceInterface
{
}

View File

@@ -0,0 +1,8 @@
<?php
namespace DesignPatterns\ServiceLocator;
class LogService implements LogServiceInterface
{
}

View File

@@ -0,0 +1,8 @@
<?php
namespace DesignPatterns\ServiceLocator;
interface LogServiceInterface
{
}

View 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...)

View 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;
}
}

View 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);
}

View File

@@ -0,0 +1,79 @@
<?php
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'));
}
}