Merge branch 'facade-a-more-abstract-example'

This commit is contained in:
Trismegiste 2013-05-11 16:21:24 +02:00
commit 189f3c3814
2 changed files with 109 additions and 0 deletions

58
Facade/Computer.php Normal file
View File

@ -0,0 +1,58 @@
<?php
/*
* DesignPatternPHP
*/
namespace DesignPatterns\Facade;
/**
* The primary goal of a Facade Pattern is not to avoid you to read the manual of
* a complex API. It's only a side-effect.
*
* The first goal is to reduce coupling and folow the Law of Demeter.
*
* A Facade is meant to decouple a client and a sub-system by embedding
* many (but sometimes just one) interface, and of course to reduce complexity.
*
* 1. A facade does not forbid you the access to the sub-system
* 2. You can (you should) have multiple facades for one sub-system
*
* That's why a good facade has no "new" in it. If there are multiple creations
* for each method, it is not a Facade, it's a Builder or a
* [Abstract|Static|Simple] Factory [Method].
*
* The best facade has no new and a constructor with interface-type-hinted parameters.
* If you need creation of new instances, use Factory as argument.
*
*/
class Computer
{
protected $opsys;
protected $bios;
/**
* This is the perfect time to use a dependency injection container
* to creaate an instance of this class
*/
public function __construct(BiosInterface $bios, OsInterface $os)
{
$this->bios = $bios;
$this->opsys = $os;
}
public function turnOn()
{
$this->bios->execute();
$this->bios->waitForKeyPress();
$this->bios->launch($this->opsys);
}
public function turnOff()
{
$this->opsys->halt();
$this->bios->powerDown();
}
}

View File

@ -0,0 +1,51 @@
<?php
/*
* DesignPatternPHP
*/
namespace DesignPatterns\Tests\Facade;
use DesignPatterns\Facade\Computer;
use DesignPatterns\Facade\Installer;
/**
* FacadeTest shows example of facades
*/
class FacadeTest extends \PHPUnit_Framework_TestCase
{
public function getComputer()
{
$bios = $this->getMockBuilder('DesignPatterns\Facade\BiosInterface')
->setMethods(array('launch', 'execute', 'waitForKeyPress'))
->disableAutoload()
->getMock();
$operatingSys = $this->getMockBuilder('DesignPatterns\Facade\OsInterface')
->setMethods(array('getName'))
->disableAutoload()
->getMock();
$bios->expects($this->once())
->method('launch')
->with($operatingSys);
$operatingSys
->expects($this->once())
->method('getName')
->will($this->returnValue('Linux'));
$facade = new Computer($bios, $operatingSys);
return array(array($facade, $operatingSys));
}
/**
* @dataProvider getComputer
*/
public function testComputerOn(Computer $facade, $os)
{
// interface is simpler :
$facade->turnOn();
// but I can access to lower component
$this->assertEquals('Linux', $os->getName());
}
}