mirror of
https://github.com/DesignPatternsPHP/DesignPatternsPHP.git
synced 2025-07-28 18:50:11 +02:00
Merge branch 'master' of github.com:domnikl/DesignPatternsPHP
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -4,3 +4,6 @@
|
|||||||
/vendor/
|
/vendor/
|
||||||
_build/
|
_build/
|
||||||
*.mo
|
*.mo
|
||||||
|
.vagrant/
|
||||||
|
phpunit.xml
|
||||||
|
composer.phar
|
||||||
|
@@ -20,8 +20,11 @@ cache:
|
|||||||
directories:
|
directories:
|
||||||
- $HOME/.composer/cache
|
- $HOME/.composer/cache
|
||||||
|
|
||||||
before_script:
|
before_install:
|
||||||
- composer self-update
|
- composer self-update
|
||||||
|
- composer validate
|
||||||
|
|
||||||
|
install:
|
||||||
- composer install --prefer-dist --no-interaction
|
- composer install --prefer-dist --no-interaction
|
||||||
|
|
||||||
script:
|
script:
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Behavioral\ChainOfResponsibilities;
|
namespace DesignPatterns\Behavioral\ChainOfResponsibilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler is a generic handler in the chain of responsibilities
|
* Handler is a generic handler in the chain of responsibilities.
|
||||||
*
|
*
|
||||||
* Yes you could have a lighter CoR with a simpler handler but if you want your CoR
|
* Yes you could have a lighter CoR with a simpler handler but if you want your CoR
|
||||||
* to be extendable and decoupled, it's a better idea to do things like that in real
|
* to be extendable and decoupled, it's a better idea to do things like that in real
|
||||||
@@ -18,7 +18,7 @@ abstract class Handler
|
|||||||
private $successor = null;
|
private $successor = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append a responsibility to the end of chain
|
* Append a responsibility to the end of chain.
|
||||||
*
|
*
|
||||||
* A prepend method could be done with the same spirit
|
* A prepend method could be done with the same spirit
|
||||||
*
|
*
|
||||||
@@ -68,7 +68,7 @@ abstract class Handler
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Each concrete handler has to implement the processing of the request
|
* Each concrete handler has to implement the processing of the request.
|
||||||
*
|
*
|
||||||
* @param Request $req
|
* @param Request $req
|
||||||
*
|
*
|
||||||
|
@@ -6,7 +6,7 @@ use DesignPatterns\Behavioral\ChainOfResponsibilities\Handler;
|
|||||||
use DesignPatterns\Behavioral\ChainOfResponsibilities\Request;
|
use DesignPatterns\Behavioral\ChainOfResponsibilities\Request;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class FastStorage
|
* Class FastStorage.
|
||||||
*/
|
*/
|
||||||
class FastStorage extends Handler
|
class FastStorage extends Handler
|
||||||
{
|
{
|
||||||
|
@@ -6,14 +6,13 @@ use DesignPatterns\Behavioral\ChainOfResponsibilities\Handler;
|
|||||||
use DesignPatterns\Behavioral\ChainOfResponsibilities\Request;
|
use DesignPatterns\Behavioral\ChainOfResponsibilities\Request;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is mostly the same code as FastStorage but in fact, it may greatly differs
|
* This is mostly the same code as FastStorage but in fact, it may greatly differs.
|
||||||
*
|
*
|
||||||
* One important fact about CoR: each item in the chain MUST NOT assume its position
|
* One important fact about CoR: each item in the chain MUST NOT assume its position
|
||||||
* in the chain. A CoR is not responsible if the request is not handled UNLESS
|
* in the chain. A CoR is not responsible if the request is not handled UNLESS
|
||||||
* you make an "ExceptionHandler" which throws execption if the request goes there.
|
* you make an "ExceptionHandler" which throws exception if the request goes there.
|
||||||
*
|
*
|
||||||
* To be really extendable, each handler doesn't know if there is something after it.
|
* To be really extendable, each handler doesn't know if there is something after it.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
class SlowStorage extends Handler
|
class SlowStorage extends Handler
|
||||||
{
|
{
|
||||||
|
@@ -3,16 +3,15 @@
|
|||||||
namespace DesignPatterns\Behavioral\ChainOfResponsibilities\Tests;
|
namespace DesignPatterns\Behavioral\ChainOfResponsibilities\Tests;
|
||||||
|
|
||||||
use DesignPatterns\Behavioral\ChainOfResponsibilities\Request;
|
use DesignPatterns\Behavioral\ChainOfResponsibilities\Request;
|
||||||
|
use DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible;
|
||||||
use DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\FastStorage;
|
use DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\FastStorage;
|
||||||
use DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\SlowStorage;
|
use DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\SlowStorage;
|
||||||
use DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ChainTest tests the CoR
|
* ChainTest tests the CoR.
|
||||||
*/
|
*/
|
||||||
class ChainTest extends \PHPUnit_Framework_TestCase
|
class ChainTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var FastStorage
|
* @var FastStorage
|
||||||
*/
|
*/
|
||||||
@@ -30,7 +29,7 @@ class ChainTest extends \PHPUnit_Framework_TestCase
|
|||||||
$request->verb = 'get';
|
$request->verb = 'get';
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
array($request)
|
array($request),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
46
Behavioral/Command/AddMessageDateCommand.php
Normal file
46
Behavioral/Command/AddMessageDateCommand.php
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Behavioral\Command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This concrete command tweaks receiver to add current date to messages
|
||||||
|
* invoker just knows that it can call "execute".
|
||||||
|
*/
|
||||||
|
class AddMessageDateCommand implements UndoableCommandInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Receiver
|
||||||
|
*/
|
||||||
|
protected $output;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Each concrete command is built with different receivers.
|
||||||
|
* There can be one, many or completely no receivers, but there can be other commands in the parameters.
|
||||||
|
*
|
||||||
|
* @param Receiver $console
|
||||||
|
*/
|
||||||
|
public function __construct(Receiver $console)
|
||||||
|
{
|
||||||
|
$this->output = $console;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute and make receiver to enable displaying messages date.
|
||||||
|
*/
|
||||||
|
public function execute()
|
||||||
|
{
|
||||||
|
// sometimes, there is no receiver and this is the command which
|
||||||
|
// does all the work
|
||||||
|
$this->output->enableDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undo the command and make receiver to disable displaying messages date.
|
||||||
|
*/
|
||||||
|
public function undo()
|
||||||
|
{
|
||||||
|
// sometimes, there is no receiver and this is the command which
|
||||||
|
// does all the work
|
||||||
|
$this->output->disableDate();
|
||||||
|
}
|
||||||
|
}
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Behavioral\Command;
|
namespace DesignPatterns\Behavioral\Command;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* class CommandInterface
|
* class CommandInterface.
|
||||||
*/
|
*/
|
||||||
interface CommandInterface
|
interface CommandInterface
|
||||||
{
|
{
|
||||||
|
@@ -4,7 +4,7 @@ namespace DesignPatterns\Behavioral\Command;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This concrete command calls "print" on the Receiver, but an external
|
* This concrete command calls "print" on the Receiver, but an external
|
||||||
* invoker just know he can call "execute"
|
* invoker just knows that it can call "execute".
|
||||||
*/
|
*/
|
||||||
class HelloCommand implements CommandInterface
|
class HelloCommand implements CommandInterface
|
||||||
{
|
{
|
||||||
@@ -14,8 +14,8 @@ class HelloCommand implements CommandInterface
|
|||||||
protected $output;
|
protected $output;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Each concrete command is builded with different receivers.
|
* Each concrete command is built with different receivers.
|
||||||
* Can be one, many, none or even other Command in parameters
|
* There can be one, many or completely no receivers, but there can be other commands in the parameters.
|
||||||
*
|
*
|
||||||
* @param Receiver $console
|
* @param Receiver $console
|
||||||
*/
|
*/
|
||||||
@@ -25,7 +25,7 @@ class HelloCommand implements CommandInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* execute and output "Hello World"
|
* execute and output "Hello World".
|
||||||
*/
|
*/
|
||||||
public function execute()
|
public function execute()
|
||||||
{
|
{
|
||||||
|
@@ -4,7 +4,7 @@ namespace DesignPatterns\Behavioral\Command;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoker is using the command given to it.
|
* Invoker is using the command given to it.
|
||||||
* Example : an Application in SF2
|
* Example : an Application in SF2.
|
||||||
*/
|
*/
|
||||||
class Invoker
|
class Invoker
|
||||||
{
|
{
|
||||||
@@ -25,7 +25,7 @@ class Invoker
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* executes the command
|
* executes the command.
|
||||||
*/
|
*/
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
|
@@ -3,15 +3,44 @@
|
|||||||
namespace DesignPatterns\Behavioral\Command;
|
namespace DesignPatterns\Behavioral\Command;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receiver is specific service with its own contract and can be only concrete
|
* Receiver is specific service with its own contract and can be only concrete.
|
||||||
*/
|
*/
|
||||||
class Receiver
|
class Receiver
|
||||||
{
|
{
|
||||||
|
private $enableDate = false;
|
||||||
|
|
||||||
|
private $output = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $str
|
* @param string $str
|
||||||
*/
|
*/
|
||||||
public function write($str)
|
public function write($str)
|
||||||
{
|
{
|
||||||
echo $str;
|
if ($this->enableDate) {
|
||||||
|
$str .= ' ['.date('Y-m-d').']';
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->output[] = $str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOutput()
|
||||||
|
{
|
||||||
|
return implode("\n", $this->output);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable receiver to display message date.
|
||||||
|
*/
|
||||||
|
public function enableDate()
|
||||||
|
{
|
||||||
|
$this->enableDate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable receiver to display message date.
|
||||||
|
*/
|
||||||
|
public function disableDate()
|
||||||
|
{
|
||||||
|
$this->enableDate = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,16 +2,15 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Behavioral\Command\Tests;
|
namespace DesignPatterns\Behavioral\Command\Tests;
|
||||||
|
|
||||||
|
use DesignPatterns\Behavioral\Command\HelloCommand;
|
||||||
use DesignPatterns\Behavioral\Command\Invoker;
|
use DesignPatterns\Behavioral\Command\Invoker;
|
||||||
use DesignPatterns\Behavioral\Command\Receiver;
|
use DesignPatterns\Behavioral\Command\Receiver;
|
||||||
use DesignPatterns\Behavioral\Command\HelloCommand;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CommandTest has the role of the Client in the Command Pattern
|
* CommandTest has the role of the Client in the Command Pattern.
|
||||||
*/
|
*/
|
||||||
class CommandTest extends \PHPUnit_Framework_TestCase
|
class CommandTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Invoker
|
* @var Invoker
|
||||||
*/
|
*/
|
||||||
@@ -31,7 +30,7 @@ class CommandTest extends \PHPUnit_Framework_TestCase
|
|||||||
public function testInvocation()
|
public function testInvocation()
|
||||||
{
|
{
|
||||||
$this->invoker->setCommand(new HelloCommand($this->receiver));
|
$this->invoker->setCommand(new HelloCommand($this->receiver));
|
||||||
$this->expectOutputString('Hello World');
|
|
||||||
$this->invoker->run();
|
$this->invoker->run();
|
||||||
|
$this->assertEquals($this->receiver->getOutput(), 'Hello World');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
49
Behavioral/Command/Tests/UndoableCommandTest.php
Normal file
49
Behavioral/Command/Tests/UndoableCommandTest.php
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Behavioral\Command\Tests;
|
||||||
|
|
||||||
|
use DesignPatterns\Behavioral\Command\AddMessageDateCommand;
|
||||||
|
use DesignPatterns\Behavioral\Command\HelloCommand;
|
||||||
|
use DesignPatterns\Behavioral\Command\Invoker;
|
||||||
|
use DesignPatterns\Behavioral\Command\Receiver;
|
||||||
|
use PHPUnit_Framework_TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UndoableCommandTest has the role of the Client in the Command Pattern.
|
||||||
|
*/
|
||||||
|
class UndoableCommandTest extends PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Invoker
|
||||||
|
*/
|
||||||
|
protected $invoker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Receiver
|
||||||
|
*/
|
||||||
|
protected $receiver;
|
||||||
|
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
$this->invoker = new Invoker();
|
||||||
|
$this->receiver = new Receiver();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvocation()
|
||||||
|
{
|
||||||
|
$this->invoker->setCommand(new HelloCommand($this->receiver));
|
||||||
|
$this->invoker->run();
|
||||||
|
$this->assertEquals($this->receiver->getOutput(), 'Hello World');
|
||||||
|
|
||||||
|
$messageDateCommand = new AddMessageDateCommand($this->receiver);
|
||||||
|
$messageDateCommand->execute();
|
||||||
|
|
||||||
|
$this->invoker->run();
|
||||||
|
$this->assertEquals($this->receiver->getOutput(), "Hello World\nHello World [".date('Y-m-d').']');
|
||||||
|
|
||||||
|
$messageDateCommand->undo();
|
||||||
|
|
||||||
|
$this->invoker->run();
|
||||||
|
$this->assertEquals($this->receiver->getOutput(), "Hello World\nHello World [".date('Y-m-d')."]\nHello World");
|
||||||
|
}
|
||||||
|
}
|
15
Behavioral/Command/UndoableCommandInterface.php
Normal file
15
Behavioral/Command/UndoableCommandInterface.php
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Behavioral\Command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface UndoableCommandInterface.
|
||||||
|
*/
|
||||||
|
interface UndoableCommandInterface extends CommandInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* This method is used to undo change made by command execution
|
||||||
|
* The Receiver goes in the constructor.
|
||||||
|
*/
|
||||||
|
public function undo();
|
||||||
|
}
|
@@ -4,7 +4,6 @@ namespace DesignPatterns\Behavioral\Iterator;
|
|||||||
|
|
||||||
class Book
|
class Book
|
||||||
{
|
{
|
||||||
|
|
||||||
private $author;
|
private $author;
|
||||||
|
|
||||||
private $title;
|
private $title;
|
||||||
|
@@ -4,23 +4,20 @@ namespace DesignPatterns\Behavioral\Iterator;
|
|||||||
|
|
||||||
class BookList implements \Countable
|
class BookList implements \Countable
|
||||||
{
|
{
|
||||||
|
|
||||||
private $books;
|
private $books;
|
||||||
|
|
||||||
public function getBook($bookNumberToGet)
|
public function getBook($bookNumberToGet)
|
||||||
{
|
{
|
||||||
if ((int)$bookNumberToGet <= $this->count()) {
|
if (isset($this->books[$bookNumberToGet])) {
|
||||||
return $this->books[$bookNumberToGet];
|
return $this->books[$bookNumberToGet];
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addBook(Book $book)
|
public function addBook(Book $book)
|
||||||
{
|
{
|
||||||
$this->books[] = $book;
|
$this->books[] = $book;
|
||||||
|
|
||||||
return $this->count();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function removeBook(Book $bookToRemove)
|
public function removeBook(Book $bookToRemove)
|
||||||
@@ -31,8 +28,6 @@ class BookList implements \Countable
|
|||||||
unset($this->books[$key]);
|
unset($this->books[$key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->count();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function count()
|
public function count()
|
||||||
|
@@ -4,11 +4,10 @@ namespace DesignPatterns\Behavioral\Iterator;
|
|||||||
|
|
||||||
class BookListIterator implements \Iterator
|
class BookListIterator implements \Iterator
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var BookList
|
* @var BookList
|
||||||
*/
|
*/
|
||||||
protected $bookList;
|
private $bookList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int
|
* @var int
|
||||||
@@ -21,8 +20,10 @@ class BookListIterator implements \Iterator
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the current book
|
* Return the current book.
|
||||||
|
*
|
||||||
* @link http://php.net/manual/en/iterator.current.php
|
* @link http://php.net/manual/en/iterator.current.php
|
||||||
|
*
|
||||||
* @return Book Can return any type.
|
* @return Book Can return any type.
|
||||||
*/
|
*/
|
||||||
public function current()
|
public function current()
|
||||||
@@ -32,8 +33,10 @@ class BookListIterator implements \Iterator
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* (PHP 5 >= 5.0.0)<br/>
|
* (PHP 5 >= 5.0.0)<br/>
|
||||||
* Move forward to next element
|
* Move forward to next element.
|
||||||
|
*
|
||||||
* @link http://php.net/manual/en/iterator.next.php
|
* @link http://php.net/manual/en/iterator.next.php
|
||||||
|
*
|
||||||
* @return void Any returned value is ignored.
|
* @return void Any returned value is ignored.
|
||||||
*/
|
*/
|
||||||
public function next()
|
public function next()
|
||||||
@@ -43,8 +46,10 @@ class BookListIterator implements \Iterator
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* (PHP 5 >= 5.0.0)<br/>
|
* (PHP 5 >= 5.0.0)<br/>
|
||||||
* Return the key of the current element
|
* Return the key of the current element.
|
||||||
|
*
|
||||||
* @link http://php.net/manual/en/iterator.key.php
|
* @link http://php.net/manual/en/iterator.key.php
|
||||||
|
*
|
||||||
* @return mixed scalar on success, or null on failure.
|
* @return mixed scalar on success, or null on failure.
|
||||||
*/
|
*/
|
||||||
public function key()
|
public function key()
|
||||||
@@ -54,20 +59,24 @@ class BookListIterator implements \Iterator
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* (PHP 5 >= 5.0.0)<br/>
|
* (PHP 5 >= 5.0.0)<br/>
|
||||||
* Checks if current position is valid
|
* Checks if current position is valid.
|
||||||
|
*
|
||||||
* @link http://php.net/manual/en/iterator.valid.php
|
* @link http://php.net/manual/en/iterator.valid.php
|
||||||
* @return boolean The return value will be casted to boolean and then evaluated.
|
*
|
||||||
|
* @return bool The return value will be casted to boolean and then evaluated.
|
||||||
* Returns true on success or false on failure.
|
* Returns true on success or false on failure.
|
||||||
*/
|
*/
|
||||||
public function valid()
|
public function valid()
|
||||||
{
|
{
|
||||||
return $this->currentBook < $this->bookList->count();
|
return null !== $this->bookList->getBook($this->currentBook);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (PHP 5 >= 5.0.0)<br/>
|
* (PHP 5 >= 5.0.0)<br/>
|
||||||
* Rewind the Iterator to the first element
|
* Rewind the Iterator to the first element.
|
||||||
|
*
|
||||||
* @link http://php.net/manual/en/iterator.rewind.php
|
* @link http://php.net/manual/en/iterator.rewind.php
|
||||||
|
*
|
||||||
* @return void Any returned value is ignored.
|
* @return void Any returned value is ignored.
|
||||||
*/
|
*/
|
||||||
public function rewind()
|
public function rewind()
|
||||||
|
@@ -2,8 +2,17 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Behavioral\Iterator;
|
namespace DesignPatterns\Behavioral\Iterator;
|
||||||
|
|
||||||
class BookListReverseIterator extends BookListIterator
|
class BookListReverseIterator implements \Iterator
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var BookList
|
||||||
|
*/
|
||||||
|
private $bookList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $currentBook = 0;
|
||||||
|
|
||||||
public function __construct(BookList $bookList)
|
public function __construct(BookList $bookList)
|
||||||
{
|
{
|
||||||
@@ -11,13 +20,68 @@ class BookListReverseIterator extends BookListIterator
|
|||||||
$this->currentBook = $this->bookList->count() - 1;
|
$this->currentBook = $this->bookList->count() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the current book.
|
||||||
|
*
|
||||||
|
* @link http://php.net/manual/en/iterator.current.php
|
||||||
|
*
|
||||||
|
* @return Book Can return any type.
|
||||||
|
*/
|
||||||
|
public function current()
|
||||||
|
{
|
||||||
|
return $this->bookList->getBook($this->currentBook);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (PHP 5 >= 5.0.0)<br/>
|
||||||
|
* Move forward to next element.
|
||||||
|
*
|
||||||
|
* @link http://php.net/manual/en/iterator.next.php
|
||||||
|
*
|
||||||
|
* @return void Any returned value is ignored.
|
||||||
|
*/
|
||||||
public function next()
|
public function next()
|
||||||
{
|
{
|
||||||
$this->currentBook--;
|
$this->currentBook--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (PHP 5 >= 5.0.0)<br/>
|
||||||
|
* Return the key of the current element.
|
||||||
|
*
|
||||||
|
* @link http://php.net/manual/en/iterator.key.php
|
||||||
|
*
|
||||||
|
* @return mixed scalar on success, or null on failure.
|
||||||
|
*/
|
||||||
|
public function key()
|
||||||
|
{
|
||||||
|
return $this->currentBook;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (PHP 5 >= 5.0.0)<br/>
|
||||||
|
* Checks if current position is valid.
|
||||||
|
*
|
||||||
|
* @link http://php.net/manual/en/iterator.valid.php
|
||||||
|
*
|
||||||
|
* @return bool The return value will be casted to boolean and then evaluated.
|
||||||
|
* Returns true on success or false on failure.
|
||||||
|
*/
|
||||||
public function valid()
|
public function valid()
|
||||||
{
|
{
|
||||||
return 0 <= $this->currentBook;
|
return null !== $this->bookList->getBook($this->currentBook);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (PHP 5 >= 5.0.0)<br/>
|
||||||
|
* Rewind the Iterator to the first element.
|
||||||
|
*
|
||||||
|
* @link http://php.net/manual/en/iterator.rewind.php
|
||||||
|
*
|
||||||
|
* @return void Any returned value is ignored.
|
||||||
|
*/
|
||||||
|
public function rewind()
|
||||||
|
{
|
||||||
|
$this->currentBook = $this->bookList->count() - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,6 @@ use DesignPatterns\Behavioral\Iterator\BookListReverseIterator;
|
|||||||
|
|
||||||
class IteratorTest extends \PHPUnit_Framework_TestCase
|
class IteratorTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var BookList
|
* @var BookList
|
||||||
*/
|
*/
|
||||||
@@ -30,8 +29,8 @@ class IteratorTest extends \PHPUnit_Framework_TestCase
|
|||||||
array(
|
array(
|
||||||
'Learning PHP Design Patterns by William Sanders',
|
'Learning PHP Design Patterns by William Sanders',
|
||||||
'Professional Php Design Patterns by Aaron Saray',
|
'Professional Php Design Patterns by Aaron Saray',
|
||||||
'Clean Code by Robert C. Martin'
|
'Clean Code by Robert C. Martin',
|
||||||
)
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -65,7 +64,7 @@ class IteratorTest extends \PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test BookList Remove
|
* Test BookList Remove.
|
||||||
*/
|
*/
|
||||||
public function testBookRemove()
|
public function testBookRemove()
|
||||||
{
|
{
|
||||||
|
@@ -9,7 +9,7 @@ namespace DesignPatterns\Behavioral\Mediator;
|
|||||||
abstract class Colleague
|
abstract class Colleague
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* this ensures no change in subclasses
|
* this ensures no change in subclasses.
|
||||||
*
|
*
|
||||||
* @var MediatorInterface
|
* @var MediatorInterface
|
||||||
*/
|
*/
|
||||||
@@ -25,6 +25,7 @@ abstract class Colleague
|
|||||||
}
|
}
|
||||||
|
|
||||||
// for subclasses
|
// for subclasses
|
||||||
|
|
||||||
protected function getMediator()
|
protected function getMediator()
|
||||||
{
|
{
|
||||||
return $this->mediator;
|
return $this->mediator;
|
||||||
|
@@ -2,15 +2,12 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Behavioral\Mediator;
|
namespace DesignPatterns\Behavioral\Mediator;
|
||||||
|
|
||||||
use DesignPatterns\Behavioral\Mediator\Subsystem;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mediator is the concrete Mediator for this design pattern.
|
* Mediator is the concrete Mediator for this design pattern.
|
||||||
* In this example, I have made a "Hello World" with the Mediator Pattern.
|
* In this example, I have made a "Hello World" with the Mediator Pattern.
|
||||||
*/
|
*/
|
||||||
class Mediator implements MediatorInterface
|
class Mediator implements MediatorInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Subsystem\Server
|
* @var Subsystem\Server
|
||||||
*/
|
*/
|
||||||
@@ -39,7 +36,7 @@ class Mediator implements MediatorInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* make request
|
* make request.
|
||||||
*/
|
*/
|
||||||
public function makeRequest()
|
public function makeRequest()
|
||||||
{
|
{
|
||||||
@@ -47,7 +44,8 @@ class Mediator implements MediatorInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* query db
|
* query db.
|
||||||
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function queryDb()
|
public function queryDb()
|
||||||
@@ -56,7 +54,7 @@ class Mediator implements MediatorInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* send response
|
* send response.
|
||||||
*
|
*
|
||||||
* @param string $content
|
* @param string $content
|
||||||
*/
|
*/
|
||||||
|
@@ -4,24 +4,24 @@ namespace DesignPatterns\Behavioral\Mediator;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* MediatorInterface is a contract for the Mediator
|
* MediatorInterface is a contract for the Mediator
|
||||||
* This interface is not mandatory but it is better for LSP concerns
|
* This interface is not mandatory but it is better for LSP concerns.
|
||||||
*/
|
*/
|
||||||
interface MediatorInterface
|
interface MediatorInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* sends the response
|
* sends the response.
|
||||||
*
|
*
|
||||||
* @param string $content
|
* @param string $content
|
||||||
*/
|
*/
|
||||||
public function sendResponse($content);
|
public function sendResponse($content);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* makes a request
|
* makes a request.
|
||||||
*/
|
*/
|
||||||
public function makeRequest();
|
public function makeRequest();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* queries the DB
|
* queries the DB.
|
||||||
*/
|
*/
|
||||||
public function queryDb();
|
public function queryDb();
|
||||||
}
|
}
|
||||||
|
@@ -4,8 +4,8 @@
|
|||||||
Purpose
|
Purpose
|
||||||
-------
|
-------
|
||||||
|
|
||||||
This pattern provides an easy to decouple many components working
|
This pattern provides an easy way to decouple many components working
|
||||||
together. It is a good alternative over Observer IF you have a "central
|
together. It is a good alternative to Observer IF you have a "central
|
||||||
intelligence", like a controller (but not in the sense of the MVC).
|
intelligence", like a controller (but not in the sense of the MVC).
|
||||||
|
|
||||||
All components (called Colleague) are only coupled to the
|
All components (called Colleague) are only coupled to the
|
||||||
|
@@ -5,12 +5,12 @@ namespace DesignPatterns\Behavioral\Mediator\Subsystem;
|
|||||||
use DesignPatterns\Behavioral\Mediator\Colleague;
|
use DesignPatterns\Behavioral\Mediator\Colleague;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client is a client that make request et get response
|
* Client is a client that make request et get response.
|
||||||
*/
|
*/
|
||||||
class Client extends Colleague
|
class Client extends Colleague
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* request
|
* request.
|
||||||
*/
|
*/
|
||||||
public function request()
|
public function request()
|
||||||
{
|
{
|
||||||
@@ -18,7 +18,7 @@ class Client extends Colleague
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* output content
|
* output content.
|
||||||
*
|
*
|
||||||
* @param string $content
|
* @param string $content
|
||||||
*/
|
*/
|
||||||
|
@@ -5,7 +5,7 @@ namespace DesignPatterns\Behavioral\Mediator\Subsystem;
|
|||||||
use DesignPatterns\Behavioral\Mediator\Colleague;
|
use DesignPatterns\Behavioral\Mediator\Colleague;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database is a database service
|
* Database is a database service.
|
||||||
*/
|
*/
|
||||||
class Database extends Colleague
|
class Database extends Colleague
|
||||||
{
|
{
|
||||||
@@ -14,6 +14,6 @@ class Database extends Colleague
|
|||||||
*/
|
*/
|
||||||
public function getData()
|
public function getData()
|
||||||
{
|
{
|
||||||
return "World";
|
return 'World';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,12 +5,12 @@ namespace DesignPatterns\Behavioral\Mediator\Subsystem;
|
|||||||
use DesignPatterns\Behavioral\Mediator\Colleague;
|
use DesignPatterns\Behavioral\Mediator\Colleague;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Server serves responses
|
* Server serves responses.
|
||||||
*/
|
*/
|
||||||
class Server extends Colleague
|
class Server extends Colleague
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* process on server
|
* process on server.
|
||||||
*/
|
*/
|
||||||
public function process()
|
public function process()
|
||||||
{
|
{
|
||||||
|
@@ -3,16 +3,15 @@
|
|||||||
namespace DesignPatterns\Tests\Mediator\Tests;
|
namespace DesignPatterns\Tests\Mediator\Tests;
|
||||||
|
|
||||||
use DesignPatterns\Behavioral\Mediator\Mediator;
|
use DesignPatterns\Behavioral\Mediator\Mediator;
|
||||||
use DesignPatterns\Behavioral\Mediator\Subsystem\Database;
|
|
||||||
use DesignPatterns\Behavioral\Mediator\Subsystem\Client;
|
use DesignPatterns\Behavioral\Mediator\Subsystem\Client;
|
||||||
|
use DesignPatterns\Behavioral\Mediator\Subsystem\Database;
|
||||||
use DesignPatterns\Behavioral\Mediator\Subsystem\Server;
|
use DesignPatterns\Behavioral\Mediator\Subsystem\Server;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MediatorTest tests hello world
|
* MediatorTest tests hello world.
|
||||||
*/
|
*/
|
||||||
class MediatorTest extends \PHPUnit_Framework_TestCase
|
class MediatorTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
protected $client;
|
protected $client;
|
||||||
|
|
||||||
protected function setUp()
|
protected function setUp()
|
||||||
|
@@ -4,30 +4,46 @@ namespace DesignPatterns\Behavioral\Memento;
|
|||||||
|
|
||||||
class Caretaker
|
class Caretaker
|
||||||
{
|
{
|
||||||
public static function run()
|
protected $history = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Memento
|
||||||
|
*/
|
||||||
|
public function getFromHistory($id)
|
||||||
{
|
{
|
||||||
/* @var $savedStates Memento[] */
|
return $this->history[$id];
|
||||||
|
}
|
||||||
|
|
||||||
$savedStates = array();
|
/**
|
||||||
|
* @param Memento $state
|
||||||
|
*/
|
||||||
|
public function saveToHistory(Memento $state)
|
||||||
|
{
|
||||||
|
$this->history[] = $state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function runCustomLogic()
|
||||||
|
{
|
||||||
$originator = new Originator();
|
$originator = new Originator();
|
||||||
|
|
||||||
//Setting state to State1
|
//Setting state to State1
|
||||||
$originator->setState("State1");
|
$originator->setState('State1');
|
||||||
//Setting state to State2
|
//Setting state to State2
|
||||||
$originator->setState("State2");
|
$originator->setState('State2');
|
||||||
//Saving State2 to Memento
|
//Saving State2 to Memento
|
||||||
$savedStates[] = $originator->saveToMemento();
|
$this->saveToHistory($originator->getStateAsMemento());
|
||||||
//Setting state to State3
|
//Setting state to State3
|
||||||
$originator->setState("State3");
|
$originator->setState('State3');
|
||||||
|
|
||||||
// We can request multiple mementos, and choose which one to roll back to.
|
// We can request multiple mementos, and choose which one to roll back to.
|
||||||
// Saving State3 to Memento
|
// Saving State3 to Memento
|
||||||
$savedStates[] = $originator->saveToMemento();
|
$this->saveToHistory($originator->getStateAsMemento());
|
||||||
//Setting state to State4
|
//Setting state to State4
|
||||||
$originator->setState("State4");
|
$originator->setState('State4');
|
||||||
|
|
||||||
$originator->restoreFromMemento($savedStates[1]);
|
$originator->restoreFromMemento($this->getFromHistory(1));
|
||||||
//State after restoring from Memento: State3
|
//State after restoring from Memento: State3
|
||||||
|
|
||||||
|
return $originator->getStateAsMemento()->getState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,14 +15,17 @@ class Originator
|
|||||||
*/
|
*/
|
||||||
public function setState($state)
|
public function setState($state)
|
||||||
{
|
{
|
||||||
|
// you must check type of state inside child of this class
|
||||||
|
// or use type-hinting for full pattern implementation
|
||||||
$this->state = $state;
|
$this->state = $state;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Memento
|
* @return Memento
|
||||||
*/
|
*/
|
||||||
public function saveToMemento()
|
public function getStateAsMemento()
|
||||||
{
|
{
|
||||||
|
// you must save a separate copy in Memento
|
||||||
$state = is_object($this->state) ? clone $this->state : $this->state;
|
$state = is_object($this->state) ? clone $this->state : $this->state;
|
||||||
|
|
||||||
return new Memento($state);
|
return new Memento($state);
|
||||||
|
@@ -4,26 +4,43 @@
|
|||||||
Purpose
|
Purpose
|
||||||
-------
|
-------
|
||||||
|
|
||||||
Provide the ability to restore an object to its previous state (undo via
|
It provides the ability to restore an object to it's previous state (undo
|
||||||
rollback).
|
via rollback) or to gain access to state of the object, without revealing
|
||||||
|
it's implementation (i.e., the object is not required to have a functional
|
||||||
|
for return the current state).
|
||||||
|
|
||||||
The memento pattern is implemented with three objects: the originator, a
|
The memento pattern is implemented with three objects: the Originator, a
|
||||||
caretaker and a memento. The originator is some object that has an
|
Caretaker and a Memento.
|
||||||
internal state. The caretaker is going to do something to the
|
|
||||||
originator, but wants to be able to undo the change. The caretaker first
|
Memento – an object that *contains a concrete unique snapshot of state* of
|
||||||
asks the originator for a memento object. Then it does whatever
|
any object or resource: string, number, array, an instance of class and so on.
|
||||||
operation (or sequence of operations) it was going to do. To roll back
|
The uniqueness in this case does not imply the prohibition existence of similar
|
||||||
to the state before the operations, it returns the memento object to the
|
states in different snapshots. That means the state can be extracted as
|
||||||
originator. The memento object itself is an opaque object (one which the
|
the independent clone. Any object stored in the Memento should be
|
||||||
caretaker cannot, or should not, change). When using this pattern, care
|
*a full copy of the original object rather than a reference* to the original
|
||||||
should be taken if the originator may change other objects or resources
|
object. The Memento object is a "opaque object" (the object that no one can
|
||||||
- the memento pattern operates on a single object.
|
or should change).
|
||||||
|
|
||||||
|
Originator – it is an object that contains the *actual state of an external
|
||||||
|
object is strictly specified type*. Originator is able to create a unique
|
||||||
|
copy of this state and return it wrapped in a Memento. The Originator does
|
||||||
|
not know the history of changes. You can set a concrete state to Originator
|
||||||
|
from the outside, which will be considered as actual. The Originator must
|
||||||
|
make sure that given state corresponds the allowed type of object. Originator
|
||||||
|
may (but not should) have any methods, but they *they can't make changes to
|
||||||
|
the saved object state*.
|
||||||
|
|
||||||
|
Caretaker *controls the states history*. He may make changes to an object;
|
||||||
|
take a decision to save the state of an external object in the Originator;
|
||||||
|
ask from the Originator snapshot of the current state; or set the Originator
|
||||||
|
state to equivalence with some snapshot from history.
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
|
|
||||||
- The seed of a pseudorandom number generator
|
- The seed of a pseudorandom number generator
|
||||||
- The state in a finite state machine
|
- The state in a finite state machine
|
||||||
|
- Control for intermediate states of `ORM Model <http://en.wikipedia.org/wiki/Object-relational_mapping>`_ before saving
|
||||||
|
|
||||||
UML Diagram
|
UML Diagram
|
||||||
-----------
|
-----------
|
||||||
|
@@ -2,68 +2,161 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Behavioral\Memento\Tests;
|
namespace DesignPatterns\Behavioral\Memento\Tests;
|
||||||
|
|
||||||
|
use DesignPatterns\Behavioral\Memento\Caretaker;
|
||||||
|
use DesignPatterns\Behavioral\Memento\Memento;
|
||||||
use DesignPatterns\Behavioral\Memento\Originator;
|
use DesignPatterns\Behavioral\Memento\Originator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MementoTest tests the memento pattern
|
* MementoTest tests the memento pattern.
|
||||||
*/
|
*/
|
||||||
class MementoTest extends \PHPUnit_Framework_TestCase
|
class MementoTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
public function testUsageExample()
|
||||||
|
{
|
||||||
|
$originator = new Originator();
|
||||||
|
$caretaker = new Caretaker();
|
||||||
|
|
||||||
|
$character = new \stdClass();
|
||||||
|
// new object
|
||||||
|
$character->name = 'Gandalf';
|
||||||
|
// connect Originator to character object
|
||||||
|
$originator->setState($character);
|
||||||
|
|
||||||
|
// work on the object
|
||||||
|
$character->name = 'Gandalf the Grey';
|
||||||
|
// still change something
|
||||||
|
$character->race = 'Maia';
|
||||||
|
// time to save state
|
||||||
|
$snapshot = $originator->getStateAsMemento();
|
||||||
|
// put state to log
|
||||||
|
$caretaker->saveToHistory($snapshot);
|
||||||
|
|
||||||
|
// change something
|
||||||
|
$character->name = 'Sauron';
|
||||||
|
// and again
|
||||||
|
$character->race = 'Ainur';
|
||||||
|
// state inside the Originator was equally changed
|
||||||
|
$this->assertAttributeEquals($character, 'state', $originator);
|
||||||
|
|
||||||
|
// time to save another state
|
||||||
|
$snapshot = $originator->getStateAsMemento();
|
||||||
|
// put state to log
|
||||||
|
$caretaker->saveToHistory($snapshot);
|
||||||
|
|
||||||
|
$rollback = $caretaker->getFromHistory(0);
|
||||||
|
// return to first state
|
||||||
|
$originator->restoreFromMemento($rollback);
|
||||||
|
// use character from old state
|
||||||
|
$character = $rollback->getState();
|
||||||
|
|
||||||
|
// yes, that what we need
|
||||||
|
$this->assertEquals('Gandalf the Grey', $character->name);
|
||||||
|
// make new changes
|
||||||
|
$character->name = 'Gandalf the White';
|
||||||
|
|
||||||
|
// and Originator linked to actual object again
|
||||||
|
$this->assertAttributeEquals($character, 'state', $originator);
|
||||||
|
}
|
||||||
|
|
||||||
public function testStringState()
|
public function testStringState()
|
||||||
{
|
{
|
||||||
$originator = new Originator();
|
$originator = new Originator();
|
||||||
$originator->setState("State1");
|
$originator->setState('State1');
|
||||||
|
|
||||||
$this->assertAttributeEquals("State1", "state", $originator);
|
$this->assertAttributeEquals('State1', 'state', $originator);
|
||||||
|
|
||||||
$originator->setState("State2");
|
$originator->setState('State2');
|
||||||
|
$this->assertAttributeEquals('State2', 'state', $originator);
|
||||||
|
|
||||||
$this->assertAttributeEquals("State2", "state", $originator);
|
$snapshot = $originator->getStateAsMemento();
|
||||||
|
$this->assertAttributeEquals('State2', 'state', $snapshot);
|
||||||
|
|
||||||
$savedState = $originator->saveToMemento();
|
$originator->setState('State3');
|
||||||
|
$this->assertAttributeEquals('State3', 'state', $originator);
|
||||||
|
|
||||||
$this->assertAttributeEquals("State2", "state", $savedState);
|
$originator->restoreFromMemento($snapshot);
|
||||||
|
$this->assertAttributeEquals('State2', 'state', $originator);
|
||||||
$originator->setState("State3");
|
|
||||||
|
|
||||||
$this->assertAttributeEquals("State3", "state", $originator);
|
|
||||||
|
|
||||||
$originator->restoreFromMemento($savedState);
|
|
||||||
|
|
||||||
$this->assertAttributeEquals("State2", "state", $originator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testObjectState()
|
public function testSnapshotIsClone()
|
||||||
|
{
|
||||||
|
$originator = new Originator();
|
||||||
|
$object = new \stdClass();
|
||||||
|
|
||||||
|
$originator->setState($object);
|
||||||
|
$snapshot = $originator->getStateAsMemento();
|
||||||
|
$object->new_property = 1;
|
||||||
|
|
||||||
|
$this->assertAttributeEquals($object, 'state', $originator);
|
||||||
|
$this->assertAttributeNotEquals($object, 'state', $snapshot);
|
||||||
|
|
||||||
|
$originator->restoreFromMemento($snapshot);
|
||||||
|
$this->assertAttributeNotEquals($object, 'state', $originator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanChangeActualState()
|
||||||
|
{
|
||||||
|
$originator = new Originator();
|
||||||
|
$first_state = new \stdClass();
|
||||||
|
|
||||||
|
$originator->setState($first_state);
|
||||||
|
$snapshot = $originator->getStateAsMemento();
|
||||||
|
$second_state = $snapshot->getState();
|
||||||
|
|
||||||
|
// still actual
|
||||||
|
$first_state->first_property = 1;
|
||||||
|
// just history
|
||||||
|
$second_state->second_property = 2;
|
||||||
|
$this->assertAttributeEquals($first_state, 'state', $originator);
|
||||||
|
$this->assertAttributeNotEquals($second_state, 'state', $originator);
|
||||||
|
|
||||||
|
$originator->restoreFromMemento($snapshot);
|
||||||
|
// now it lost state
|
||||||
|
$first_state->first_property = 11;
|
||||||
|
// must be actual
|
||||||
|
$second_state->second_property = 22;
|
||||||
|
$this->assertAttributeEquals($second_state, 'state', $originator);
|
||||||
|
$this->assertAttributeNotEquals($first_state, 'state', $originator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testStateWithDifferentObjects()
|
||||||
{
|
{
|
||||||
$originator = new Originator();
|
$originator = new Originator();
|
||||||
|
|
||||||
$foo = new \stdClass();
|
$first = new \stdClass();
|
||||||
$foo->data = "foo";
|
$first->data = 'foo';
|
||||||
|
|
||||||
$originator->setState($foo);
|
$originator->setState($first);
|
||||||
|
$this->assertAttributeEquals($first, 'state', $originator);
|
||||||
|
|
||||||
$this->assertAttributeEquals($foo, "state", $originator);
|
$first_snapshot = $originator->getStateAsMemento();
|
||||||
|
$this->assertAttributeEquals($first, 'state', $first_snapshot);
|
||||||
|
|
||||||
$savedState = $originator->saveToMemento();
|
$second = new \stdClass();
|
||||||
|
$second->data = 'bar';
|
||||||
|
$originator->setState($second);
|
||||||
|
$this->assertAttributeEquals($second, 'state', $originator);
|
||||||
|
|
||||||
$this->assertAttributeEquals($foo, "state", $savedState);
|
$originator->restoreFromMemento($first_snapshot);
|
||||||
|
$this->assertAttributeEquals($first, 'state', $originator);
|
||||||
|
}
|
||||||
|
|
||||||
$bar = new \stdClass();
|
public function testCaretaker()
|
||||||
$bar->data = "bar";
|
{
|
||||||
|
$caretaker = new Caretaker();
|
||||||
|
$memento1 = new Memento('foo');
|
||||||
|
$memento2 = new Memento('bar');
|
||||||
|
$caretaker->saveToHistory($memento1);
|
||||||
|
$caretaker->saveToHistory($memento2);
|
||||||
|
$this->assertAttributeEquals(array($memento1, $memento2), 'history', $caretaker);
|
||||||
|
$this->assertEquals($memento1, $caretaker->getFromHistory(0));
|
||||||
|
$this->assertEquals($memento2, $caretaker->getFromHistory(1));
|
||||||
|
}
|
||||||
|
|
||||||
$originator->setState($bar);
|
public function testCaretakerCustomLogic()
|
||||||
|
{
|
||||||
$this->assertAttributeEquals($bar, "state", $originator);
|
$caretaker = new Caretaker();
|
||||||
|
$result = $caretaker->runCustomLogic();
|
||||||
$originator->restoreFromMemento($savedState);
|
$this->assertEquals('State3', $result);
|
||||||
|
|
||||||
$this->assertAttributeEquals($foo, "state", $originator);
|
|
||||||
|
|
||||||
$foo->data = null;
|
|
||||||
|
|
||||||
$this->assertAttributeNotEquals($foo, "state", $savedState);
|
|
||||||
|
|
||||||
$this->assertAttributeNotEquals($foo, "state", $originator);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 61 KiB |
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Behavioral\NullObject;
|
namespace DesignPatterns\Behavioral\NullObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LoggerInterface is a contract for logging something
|
* LoggerInterface is a contract for logging something.
|
||||||
*
|
*
|
||||||
* Key feature: NullLogger MUST inherit from this interface like any other Loggers
|
* Key feature: NullLogger MUST inherit from this interface like any other Loggers
|
||||||
*/
|
*/
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Behavioral\NullObject;
|
namespace DesignPatterns\Behavioral\NullObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PrintLogger is a logger that prints the log entry to standard output
|
* PrintLogger is a logger that prints the log entry to standard output.
|
||||||
*/
|
*/
|
||||||
class PrintLogger implements LoggerInterface
|
class PrintLogger implements LoggerInterface
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Behavioral\NullObject;
|
namespace DesignPatterns\Behavioral\NullObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service is dummy service that uses a logger
|
* Service is dummy service that uses a logger.
|
||||||
*/
|
*/
|
||||||
class Service
|
class Service
|
||||||
{
|
{
|
||||||
@@ -13,7 +13,7 @@ class Service
|
|||||||
protected $logger;
|
protected $logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* we inject the logger in ctor and it is mandatory
|
* we inject the logger in ctor and it is mandatory.
|
||||||
*
|
*
|
||||||
* @param LoggerInterface $log
|
* @param LoggerInterface $log
|
||||||
*/
|
*/
|
||||||
|
@@ -3,15 +3,14 @@
|
|||||||
namespace DesignPatterns\Behavioral\NullObject\Tests;
|
namespace DesignPatterns\Behavioral\NullObject\Tests;
|
||||||
|
|
||||||
use DesignPatterns\Behavioral\NullObject\NullLogger;
|
use DesignPatterns\Behavioral\NullObject\NullLogger;
|
||||||
use DesignPatterns\Behavioral\NullObject\Service;
|
|
||||||
use DesignPatterns\Behavioral\NullObject\PrintLogger;
|
use DesignPatterns\Behavioral\NullObject\PrintLogger;
|
||||||
|
use DesignPatterns\Behavioral\NullObject\Service;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LoggerTest tests for different loggers
|
* LoggerTest tests for different loggers.
|
||||||
*/
|
*/
|
||||||
class LoggerTest extends \PHPUnit_Framework_TestCase
|
class LoggerTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
public function testNullObject()
|
public function testNullObject()
|
||||||
{
|
{
|
||||||
// one can use a singleton for NullObjet : I don't think it's a good idea
|
// one can use a singleton for NullObjet : I don't think it's a good idea
|
||||||
|
@@ -2,15 +2,14 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Behavioral\Observer\Tests;
|
namespace DesignPatterns\Behavioral\Observer\Tests;
|
||||||
|
|
||||||
use DesignPatterns\Behavioral\Observer\UserObserver;
|
|
||||||
use DesignPatterns\Behavioral\Observer\User;
|
use DesignPatterns\Behavioral\Observer\User;
|
||||||
|
use DesignPatterns\Behavioral\Observer\UserObserver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ObserverTest tests the Observer pattern
|
* ObserverTest tests the Observer pattern.
|
||||||
*/
|
*/
|
||||||
class ObserverTest extends \PHPUnit_Framework_TestCase
|
class ObserverTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
protected $observer;
|
protected $observer;
|
||||||
|
|
||||||
protected function setUp()
|
protected function setUp()
|
||||||
@@ -19,7 +18,7 @@ class ObserverTest extends \PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the notification
|
* Tests the notification.
|
||||||
*/
|
*/
|
||||||
public function testNotify()
|
public function testNotify()
|
||||||
{
|
{
|
||||||
@@ -31,7 +30,7 @@ class ObserverTest extends \PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the subscribing
|
* Tests the subscribing.
|
||||||
*/
|
*/
|
||||||
public function testAttachDetach()
|
public function testAttachDetach()
|
||||||
{
|
{
|
||||||
@@ -53,7 +52,7 @@ class ObserverTest extends \PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the update() invocation on a mockup
|
* Tests the update() invocation on a mockup.
|
||||||
*/
|
*/
|
||||||
public function testUpdateCalling()
|
public function testUpdateCalling()
|
||||||
{
|
{
|
||||||
|
@@ -3,22 +3,21 @@
|
|||||||
namespace DesignPatterns\Behavioral\Observer;
|
namespace DesignPatterns\Behavioral\Observer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Observer pattern : The observed object (the subject)
|
* Observer pattern : The observed object (the subject).
|
||||||
*
|
*
|
||||||
* The subject maintains a list of Observers and sends notifications.
|
* The subject maintains a list of Observers and sends notifications.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
class User implements \SplSubject
|
class User implements \SplSubject
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* user data
|
* user data.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $data = array();
|
protected $data = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* observers
|
* observers.
|
||||||
*
|
*
|
||||||
* @var \SplObjectStorage
|
* @var \SplObjectStorage
|
||||||
*/
|
*/
|
||||||
@@ -30,7 +29,7 @@ class User implements \SplSubject
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* attach a new observer
|
* attach a new observer.
|
||||||
*
|
*
|
||||||
* @param \SplObserver $observer
|
* @param \SplObserver $observer
|
||||||
*
|
*
|
||||||
@@ -42,7 +41,7 @@ class User implements \SplSubject
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* detach an observer
|
* detach an observer.
|
||||||
*
|
*
|
||||||
* @param \SplObserver $observer
|
* @param \SplObserver $observer
|
||||||
*
|
*
|
||||||
@@ -54,7 +53,7 @@ class User implements \SplSubject
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* notify observers
|
* notify observers.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
@@ -68,7 +67,7 @@ class User implements \SplSubject
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Ideally one would better write setter/getter for all valid attributes and only call notify()
|
* Ideally one would better write setter/getter for all valid attributes and only call notify()
|
||||||
* on attributes that matter when changed
|
* on attributes that matter when changed.
|
||||||
*
|
*
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
|
@@ -3,13 +3,13 @@
|
|||||||
namespace DesignPatterns\Behavioral\Observer;
|
namespace DesignPatterns\Behavioral\Observer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* class UserObserver
|
* class UserObserver.
|
||||||
*/
|
*/
|
||||||
class UserObserver implements \SplObserver
|
class UserObserver implements \SplObserver
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* This is the only method to implement as an observer.
|
* This is the only method to implement as an observer.
|
||||||
* It is called by the Subject (usually by SplSubject::notify() )
|
* It is called by the Subject (usually by SplSubject::notify() ).
|
||||||
*
|
*
|
||||||
* @param \SplSubject $subject
|
* @param \SplSubject $subject
|
||||||
*/
|
*/
|
||||||
|
@@ -9,7 +9,7 @@ communication.
|
|||||||
* [Command](Command) [:notebook:](http://en.wikipedia.org/wiki/Command_pattern)
|
* [Command](Command) [:notebook:](http://en.wikipedia.org/wiki/Command_pattern)
|
||||||
* [Iterator](Iterator) [:notebook:](http://en.wikipedia.org/wiki/Iterator_pattern)
|
* [Iterator](Iterator) [:notebook:](http://en.wikipedia.org/wiki/Iterator_pattern)
|
||||||
* [Mediator](Mediator) [:notebook:](http://en.wikipedia.org/wiki/Mediator_pattern)
|
* [Mediator](Mediator) [:notebook:](http://en.wikipedia.org/wiki/Mediator_pattern)
|
||||||
* [Memento](Behavioral/Memento) [:notebook:](http://en.wikipedia.org/wiki/Memento_pattern)
|
* [Memento](Memento) [:notebook:](http://en.wikipedia.org/wiki/Memento_pattern)
|
||||||
* [NullObject](NullObject) [:notebook:](http://en.wikipedia.org/wiki/Null_Object_pattern)
|
* [NullObject](NullObject) [:notebook:](http://en.wikipedia.org/wiki/Null_Object_pattern)
|
||||||
* [Observer](Observer) [:notebook:](http://en.wikipedia.org/wiki/Observer_pattern)
|
* [Observer](Observer) [:notebook:](http://en.wikipedia.org/wiki/Observer_pattern)
|
||||||
* [Specification](Specification) [:notebook:](http://en.wikipedia.org/wiki/Specification_pattern)
|
* [Specification](Specification) [:notebook:](http://en.wikipedia.org/wiki/Specification_pattern)
|
||||||
|
@@ -1,13 +1,14 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Behavioral\Specification;
|
namespace DesignPatterns\Behavioral\Specification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract specification allows the creation of wrapped specifications
|
* An abstract specification allows the creation of wrapped specifications.
|
||||||
*/
|
*/
|
||||||
abstract class AbstractSpecification implements SpecificationInterface
|
abstract class AbstractSpecification implements SpecificationInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Checks if given item meets all criteria
|
* Checks if given item meets all criteria.
|
||||||
*
|
*
|
||||||
* @param Item $item
|
* @param Item $item
|
||||||
*
|
*
|
||||||
@@ -16,7 +17,7 @@ abstract class AbstractSpecification implements SpecificationInterface
|
|||||||
abstract public function isSatisfiedBy(Item $item);
|
abstract public function isSatisfiedBy(Item $item);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new logical AND specification
|
* Creates a new logical AND specification.
|
||||||
*
|
*
|
||||||
* @param SpecificationInterface $spec
|
* @param SpecificationInterface $spec
|
||||||
*
|
*
|
||||||
@@ -28,7 +29,7 @@ abstract class AbstractSpecification implements SpecificationInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new logical OR composite specification
|
* Creates a new logical OR composite specification.
|
||||||
*
|
*
|
||||||
* @param SpecificationInterface $spec
|
* @param SpecificationInterface $spec
|
||||||
*
|
*
|
||||||
@@ -40,7 +41,7 @@ abstract class AbstractSpecification implements SpecificationInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new logical NOT specification
|
* Creates a new logical NOT specification.
|
||||||
*
|
*
|
||||||
* @return SpecificationInterface
|
* @return SpecificationInterface
|
||||||
*/
|
*/
|
||||||
|
@@ -1,17 +1,17 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Behavioral\Specification;
|
namespace DesignPatterns\Behavioral\Specification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A logical OR specification
|
* A logical OR specification.
|
||||||
*/
|
*/
|
||||||
class Either extends AbstractSpecification
|
class Either extends AbstractSpecification
|
||||||
{
|
{
|
||||||
|
|
||||||
protected $left;
|
protected $left;
|
||||||
protected $right;
|
protected $right;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A composite wrapper of two specifications
|
* A composite wrapper of two specifications.
|
||||||
*
|
*
|
||||||
* @param SpecificationInterface $left
|
* @param SpecificationInterface $left
|
||||||
* @param SpecificationInterface $right
|
* @param SpecificationInterface $right
|
||||||
@@ -23,7 +23,7 @@ class Either extends AbstractSpecification
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the evaluation of both wrapped specifications as a logical OR
|
* Returns the evaluation of both wrapped specifications as a logical OR.
|
||||||
*
|
*
|
||||||
* @param Item $item
|
* @param Item $item
|
||||||
*
|
*
|
||||||
|
@@ -1,15 +1,16 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Behavioral\Specification;
|
namespace DesignPatterns\Behavioral\Specification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An trivial item
|
* An trivial item.
|
||||||
*/
|
*/
|
||||||
class Item
|
class Item
|
||||||
{
|
{
|
||||||
protected $price;
|
protected $price;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An item must have a price
|
* An item must have a price.
|
||||||
*
|
*
|
||||||
* @param int $price
|
* @param int $price
|
||||||
*/
|
*/
|
||||||
@@ -19,7 +20,7 @@ class Item
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the items price
|
* Get the items price.
|
||||||
*
|
*
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
|
@@ -1,16 +1,16 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Behavioral\Specification;
|
namespace DesignPatterns\Behavioral\Specification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A logical Not specification
|
* A logical Not specification.
|
||||||
*/
|
*/
|
||||||
class Not extends AbstractSpecification
|
class Not extends AbstractSpecification
|
||||||
{
|
{
|
||||||
|
|
||||||
protected $spec;
|
protected $spec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new specification wrapping another
|
* Creates a new specification wrapping another.
|
||||||
*
|
*
|
||||||
* @param SpecificationInterface $spec
|
* @param SpecificationInterface $spec
|
||||||
*/
|
*/
|
||||||
@@ -20,7 +20,7 @@ class Not extends AbstractSpecification
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the negated result of the wrapped specification
|
* Returns the negated result of the wrapped specification.
|
||||||
*
|
*
|
||||||
* @param Item $item
|
* @param Item $item
|
||||||
*
|
*
|
||||||
|
@@ -1,17 +1,17 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Behavioral\Specification;
|
namespace DesignPatterns\Behavioral\Specification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A logical AND specification
|
* A logical AND specification.
|
||||||
*/
|
*/
|
||||||
class Plus extends AbstractSpecification
|
class Plus extends AbstractSpecification
|
||||||
{
|
{
|
||||||
|
|
||||||
protected $left;
|
protected $left;
|
||||||
protected $right;
|
protected $right;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creation of a logical AND of two specifications
|
* Creation of a logical AND of two specifications.
|
||||||
*
|
*
|
||||||
* @param SpecificationInterface $left
|
* @param SpecificationInterface $left
|
||||||
* @param SpecificationInterface $right
|
* @param SpecificationInterface $right
|
||||||
@@ -23,7 +23,7 @@ class Plus extends AbstractSpecification
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the composite AND of specifications passes
|
* Checks if the composite AND of specifications passes.
|
||||||
*
|
*
|
||||||
* @param Item $item
|
* @param Item $item
|
||||||
*
|
*
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Behavioral\Specification;
|
namespace DesignPatterns\Behavioral\Specification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A specification to check an Item is priced between min and max
|
* A specification to check an Item is priced between min and max.
|
||||||
*/
|
*/
|
||||||
class PriceSpecification extends AbstractSpecification
|
class PriceSpecification extends AbstractSpecification
|
||||||
{
|
{
|
||||||
@@ -10,7 +11,7 @@ class PriceSpecification extends AbstractSpecification
|
|||||||
protected $minPrice;
|
protected $minPrice;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the optional maximum price
|
* Sets the optional maximum price.
|
||||||
*
|
*
|
||||||
* @param int $maxPrice
|
* @param int $maxPrice
|
||||||
*/
|
*/
|
||||||
@@ -20,7 +21,7 @@ class PriceSpecification extends AbstractSpecification
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the optional minimum price
|
* Sets the optional minimum price.
|
||||||
*
|
*
|
||||||
* @param int $minPrice
|
* @param int $minPrice
|
||||||
*/
|
*/
|
||||||
@@ -30,7 +31,7 @@ class PriceSpecification extends AbstractSpecification
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if Item price falls between bounds
|
* Checks if Item price falls between bounds.
|
||||||
*
|
*
|
||||||
* @param Item $item
|
* @param Item $item
|
||||||
*
|
*
|
||||||
|
@@ -1,13 +1,14 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Behavioral\Specification;
|
namespace DesignPatterns\Behavioral\Specification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface for a specification
|
* An interface for a specification.
|
||||||
*/
|
*/
|
||||||
interface SpecificationInterface
|
interface SpecificationInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* A boolean evaluation indicating if the object meets the specification
|
* A boolean evaluation indicating if the object meets the specification.
|
||||||
*
|
*
|
||||||
* @param Item $item
|
* @param Item $item
|
||||||
*
|
*
|
||||||
@@ -16,21 +17,21 @@ interface SpecificationInterface
|
|||||||
public function isSatisfiedBy(Item $item);
|
public function isSatisfiedBy(Item $item);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a logical AND specification
|
* Creates a logical AND specification.
|
||||||
*
|
*
|
||||||
* @param SpecificationInterface $spec
|
* @param SpecificationInterface $spec
|
||||||
*/
|
*/
|
||||||
public function plus(SpecificationInterface $spec);
|
public function plus(SpecificationInterface $spec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a logical OR specification
|
* Creates a logical OR specification.
|
||||||
*
|
*
|
||||||
* @param SpecificationInterface $spec
|
* @param SpecificationInterface $spec
|
||||||
*/
|
*/
|
||||||
public function either(SpecificationInterface $spec);
|
public function either(SpecificationInterface $spec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a logical not specification
|
* Creates a logical not specification.
|
||||||
*/
|
*/
|
||||||
public function not();
|
public function not();
|
||||||
}
|
}
|
||||||
|
@@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Behavioral\Specification\Tests;
|
namespace DesignPatterns\Behavioral\Specification\Tests;
|
||||||
|
|
||||||
use DesignPatterns\Behavioral\Specification\PriceSpecification;
|
|
||||||
use DesignPatterns\Behavioral\Specification\Item;
|
use DesignPatterns\Behavioral\Specification\Item;
|
||||||
|
use DesignPatterns\Behavioral\Specification\PriceSpecification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SpecificationTest tests the specification pattern
|
* SpecificationTest tests the specification pattern.
|
||||||
*/
|
*/
|
||||||
class SpecificationTest extends \PHPUnit_Framework_TestCase
|
class SpecificationTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Behavioral\State;
|
namespace DesignPatterns\Behavioral\State;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class CreateOrder
|
* Class CreateOrder.
|
||||||
*/
|
*/
|
||||||
class CreateOrder implements OrderInterface
|
class CreateOrder implements OrderInterface
|
||||||
{
|
{
|
||||||
@@ -38,8 +38,9 @@ class CreateOrder implements OrderInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return mixed|void
|
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
|
*
|
||||||
|
* @return mixed|void
|
||||||
*/
|
*/
|
||||||
public function completeOrder()
|
public function completeOrder()
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Behavioral\State;
|
namespace DesignPatterns\Behavioral\State;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class OrderController
|
* Class OrderController.
|
||||||
*/
|
*/
|
||||||
class OrderController
|
class OrderController
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Behavioral\State;
|
namespace DesignPatterns\Behavioral\State;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class OrderFactory
|
* Class OrderFactory.
|
||||||
*/
|
*/
|
||||||
class OrderFactory
|
class OrderFactory
|
||||||
{
|
{
|
||||||
@@ -15,8 +15,9 @@ class OrderFactory
|
|||||||
/**
|
/**
|
||||||
* @param int $id
|
* @param int $id
|
||||||
*
|
*
|
||||||
* @return CreateOrder|ShippingOrder
|
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
|
*
|
||||||
|
* @return CreateOrder|ShippingOrder
|
||||||
*/
|
*/
|
||||||
public static function getOrder($id)
|
public static function getOrder($id)
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Behavioral\State;
|
namespace DesignPatterns\Behavioral\State;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class OrderInterface
|
* Class OrderInterface.
|
||||||
*/
|
*/
|
||||||
interface OrderInterface
|
interface OrderInterface
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Behavioral\State;
|
namespace DesignPatterns\Behavioral\State;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ShippingOrder
|
* Class ShippingOrder.
|
||||||
*/
|
*/
|
||||||
class ShippingOrder implements OrderInterface
|
class ShippingOrder implements OrderInterface
|
||||||
{
|
{
|
||||||
@@ -26,8 +26,9 @@ class ShippingOrder implements OrderInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return mixed|void
|
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
|
*
|
||||||
|
* @return mixed|void
|
||||||
*/
|
*/
|
||||||
public function shipOrder()
|
public function shipOrder()
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Behavioral\Strategy;
|
namespace DesignPatterns\Behavioral\Strategy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ComparatorInterface
|
* Class ComparatorInterface.
|
||||||
*/
|
*/
|
||||||
interface ComparatorInterface
|
interface ComparatorInterface
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Behavioral\Strategy;
|
namespace DesignPatterns\Behavioral\Strategy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class DateComparator
|
* Class DateComparator.
|
||||||
*/
|
*/
|
||||||
class DateComparator implements ComparatorInterface
|
class DateComparator implements ComparatorInterface
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Behavioral\Strategy;
|
namespace DesignPatterns\Behavioral\Strategy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class IdComparator
|
* Class IdComparator.
|
||||||
*/
|
*/
|
||||||
class IdComparator implements ComparatorInterface
|
class IdComparator implements ComparatorInterface
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Behavioral\Strategy;
|
namespace DesignPatterns\Behavioral\Strategy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ObjectCollection
|
* Class ObjectCollection.
|
||||||
*/
|
*/
|
||||||
class ObjectCollection
|
class ObjectCollection
|
||||||
{
|
{
|
||||||
@@ -31,7 +31,7 @@ class ObjectCollection
|
|||||||
public function sort()
|
public function sort()
|
||||||
{
|
{
|
||||||
if (!$this->comparator) {
|
if (!$this->comparator) {
|
||||||
throw new \LogicException("Comparator is not set");
|
throw new \LogicException('Comparator is not set');
|
||||||
}
|
}
|
||||||
|
|
||||||
$callback = array($this->comparator, 'compare');
|
$callback = array($this->comparator, 'compare');
|
||||||
|
@@ -8,21 +8,20 @@ use DesignPatterns\Behavioral\Strategy\ObjectCollection;
|
|||||||
use DesignPatterns\Behavioral\Strategy\Strategy;
|
use DesignPatterns\Behavioral\Strategy\Strategy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for Strategy pattern
|
* Tests for Strategy pattern.
|
||||||
*/
|
*/
|
||||||
class StrategyTest extends \PHPUnit_Framework_TestCase
|
class StrategyTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
public function getIdCollection()
|
public function getIdCollection()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
array(
|
array(
|
||||||
array(array('id' => 2), array('id' => 1), array('id' => 3)),
|
array(array('id' => 2), array('id' => 1), array('id' => 3)),
|
||||||
array('id' => 1)
|
array('id' => 1),
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
array(array('id' => 3), array('id' => 2), array('id' => 1)),
|
array(array('id' => 3), array('id' => 2), array('id' => 1)),
|
||||||
array('id' => 1)
|
array('id' => 1),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -32,11 +31,11 @@ class StrategyTest extends \PHPUnit_Framework_TestCase
|
|||||||
return array(
|
return array(
|
||||||
array(
|
array(
|
||||||
array(array('date' => '2014-03-03'), array('date' => '2015-03-02'), array('date' => '2013-03-01')),
|
array(array('date' => '2014-03-03'), array('date' => '2015-03-02'), array('date' => '2013-03-01')),
|
||||||
array('date' => '2013-03-01')
|
array('date' => '2013-03-01'),
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
array(array('date' => '2014-02-03'), array('date' => '2013-02-01'), array('date' => '2015-02-02')),
|
array(array('date' => '2014-02-03'), array('date' => '2013-02-01'), array('date' => '2015-02-02')),
|
||||||
array('date' => '2013-02-01')
|
array('date' => '2013-02-01'),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -3,12 +3,12 @@
|
|||||||
namespace DesignPatterns\Behavioral\TemplateMethod;
|
namespace DesignPatterns\Behavioral\TemplateMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BeachJourney is vacation at the beach
|
* BeachJourney is vacation at the beach.
|
||||||
*/
|
*/
|
||||||
class BeachJourney extends Journey
|
class BeachJourney extends Journey
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* prints what to do to enjoy your vacation
|
* prints what to do to enjoy your vacation.
|
||||||
*/
|
*/
|
||||||
protected function enjoyVacation()
|
protected function enjoyVacation()
|
||||||
{
|
{
|
||||||
|
@@ -3,12 +3,12 @@
|
|||||||
namespace DesignPatterns\Behavioral\TemplateMethod;
|
namespace DesignPatterns\Behavioral\TemplateMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CityJourney is a journey in a city
|
* CityJourney is a journey in a city.
|
||||||
*/
|
*/
|
||||||
class CityJourney extends Journey
|
class CityJourney extends Journey
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* prints what to do in your journey to enjoy vacation
|
* prints what to do in your journey to enjoy vacation.
|
||||||
*/
|
*/
|
||||||
protected function enjoyVacation()
|
protected function enjoyVacation()
|
||||||
{
|
{
|
||||||
|
@@ -23,7 +23,7 @@ abstract class Journey
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method must be implemented, this is the key-feature of this pattern
|
* This method must be implemented, this is the key-feature of this pattern.
|
||||||
*/
|
*/
|
||||||
abstract protected function enjoyVacation();
|
abstract protected function enjoyVacation();
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ abstract class Journey
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will be unknown by subclasses (better)
|
* This method will be unknown by subclasses (better).
|
||||||
*/
|
*/
|
||||||
private function buyAFlight()
|
private function buyAFlight()
|
||||||
{
|
{
|
||||||
@@ -46,7 +46,7 @@ abstract class Journey
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclasses will get access to this method but cannot override it and
|
* Subclasses will get access to this method but cannot override it and
|
||||||
* compromise this algorithm (warning : cause of cyclic dependencies)
|
* compromise this algorithm (warning : cause of cyclic dependencies).
|
||||||
*/
|
*/
|
||||||
final protected function takePlane()
|
final protected function takePlane()
|
||||||
{
|
{
|
||||||
|
@@ -5,11 +5,10 @@ namespace DesignPatterns\Behavioral\TemplateMethod\Tests;
|
|||||||
use DesignPatterns\Behavioral\TemplateMethod;
|
use DesignPatterns\Behavioral\TemplateMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JourneyTest tests all journeys
|
* JourneyTest tests all journeys.
|
||||||
*/
|
*/
|
||||||
class JourneyTest extends \PHPUnit_Framework_TestCase
|
class JourneyTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
public function testBeach()
|
public function testBeach()
|
||||||
{
|
{
|
||||||
$journey = new TemplateMethod\BeachJourney();
|
$journey = new TemplateMethod\BeachJourney();
|
||||||
@@ -25,7 +24,7 @@ class JourneyTest extends \PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How to test an abstract template method with PHPUnit
|
* How to test an abstract template method with PHPUnit.
|
||||||
*/
|
*/
|
||||||
public function testLasVegas()
|
public function testLasVegas()
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Behavioral\Visitor;
|
namespace DesignPatterns\Behavioral\Visitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An example of a Visitor: Group
|
* An example of a Visitor: Group.
|
||||||
*/
|
*/
|
||||||
class Group extends Role
|
class Group extends Role
|
||||||
{
|
{
|
||||||
@@ -25,6 +25,6 @@ class Group extends Role
|
|||||||
*/
|
*/
|
||||||
public function getName()
|
public function getName()
|
||||||
{
|
{
|
||||||
return "Group: " . $this->name;
|
return 'Group: '.$this->name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,12 +3,12 @@
|
|||||||
namespace DesignPatterns\Behavioral\Visitor;
|
namespace DesignPatterns\Behavioral\Visitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* class Role
|
* class Role.
|
||||||
*/
|
*/
|
||||||
abstract class Role
|
abstract class Role
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* This method handles a double dispatch based on the short name of the Visitor
|
* This method handles a double dispatch based on the short name of the Visitor.
|
||||||
*
|
*
|
||||||
* Feel free to override it if your object must call another visiting behavior
|
* Feel free to override it if your object must call another visiting behavior
|
||||||
*
|
*
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Behavioral\Visitor;
|
namespace DesignPatterns\Behavioral\Visitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visitor Pattern
|
* Visitor Pattern.
|
||||||
*
|
*
|
||||||
* An implementation of a concrete Visitor
|
* An implementation of a concrete Visitor
|
||||||
*/
|
*/
|
||||||
@@ -14,7 +14,7 @@ class RolePrintVisitor implements RoleVisitorInterface
|
|||||||
*/
|
*/
|
||||||
public function visitGroup(Group $role)
|
public function visitGroup(Group $role)
|
||||||
{
|
{
|
||||||
echo "Role: " . $role->getName();
|
echo 'Role: '.$role->getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -22,6 +22,6 @@ class RolePrintVisitor implements RoleVisitorInterface
|
|||||||
*/
|
*/
|
||||||
public function visitUser(User $role)
|
public function visitUser(User $role)
|
||||||
{
|
{
|
||||||
echo "Role: " . $role->getName();
|
echo 'Role: '.$role->getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,11 +3,11 @@
|
|||||||
namespace DesignPatterns\Behavioral\Visitor;
|
namespace DesignPatterns\Behavioral\Visitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visitor Pattern
|
* Visitor Pattern.
|
||||||
*
|
*
|
||||||
* The contract for the visitor.
|
* The contract for the visitor.
|
||||||
*
|
*
|
||||||
* Note 1 : in C++ or java, with method polymorphism based on type-hint, there are many
|
* Note 1 : in C++ or Java, with method polymorphism based on type-hint, there are many
|
||||||
* methods visit() with different type for the 'role' parameter.
|
* methods visit() with different type for the 'role' parameter.
|
||||||
*
|
*
|
||||||
* Note 2 : the visitor must not choose itself which method to
|
* Note 2 : the visitor must not choose itself which method to
|
||||||
@@ -16,14 +16,14 @@ namespace DesignPatterns\Behavioral\Visitor;
|
|||||||
interface RoleVisitorInterface
|
interface RoleVisitorInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Visit a User object
|
* Visit a User object.
|
||||||
*
|
*
|
||||||
* @param \DesignPatterns\Behavioral\Visitor\User $role
|
* @param \DesignPatterns\Behavioral\Visitor\User $role
|
||||||
*/
|
*/
|
||||||
public function visitUser(User $role);
|
public function visitUser(User $role);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visit a Group object
|
* Visit a Group object.
|
||||||
*
|
*
|
||||||
* @param \DesignPatterns\Behavioral\Visitor\Group $role
|
* @param \DesignPatterns\Behavioral\Visitor\Group $role
|
||||||
*/
|
*/
|
||||||
|
@@ -5,11 +5,10 @@ namespace DesignPatterns\Tests\Visitor\Tests;
|
|||||||
use DesignPatterns\Behavioral\Visitor;
|
use DesignPatterns\Behavioral\Visitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VisitorTest tests the visitor pattern
|
* VisitorTest tests the visitor pattern.
|
||||||
*/
|
*/
|
||||||
class VisitorTest extends \PHPUnit_Framework_TestCase
|
class VisitorTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
protected $visitor;
|
protected $visitor;
|
||||||
|
|
||||||
protected function setUp()
|
protected function setUp()
|
||||||
@@ -20,8 +19,8 @@ class VisitorTest extends \PHPUnit_Framework_TestCase
|
|||||||
public function getRole()
|
public function getRole()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
array(new Visitor\User("Dominik"), 'Role: User Dominik'),
|
array(new Visitor\User('Dominik'), 'Role: User Dominik'),
|
||||||
array(new Visitor\Group("Administrators"), 'Role: Group: Administrators')
|
array(new Visitor\Group('Administrators'), 'Role: Group: Administrators'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Behavioral\Visitor;
|
namespace DesignPatterns\Behavioral\Visitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visitor Pattern
|
* Visitor Pattern.
|
||||||
*
|
*
|
||||||
* One example for a visitee. Each visitee has to extends Role
|
* One example for a visitee. Each visitee has to extends Role
|
||||||
*/
|
*/
|
||||||
@@ -27,6 +27,6 @@ class User extends Role
|
|||||||
*/
|
*/
|
||||||
public function getName()
|
public function getName()
|
||||||
{
|
{
|
||||||
return "User " . $this->name;
|
return 'User '.$this->name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Creational\AbstractFactory;
|
namespace DesignPatterns\Creational\AbstractFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* class AbstractFactory
|
* class AbstractFactory.
|
||||||
*
|
*
|
||||||
* Sometimes also known as "Kit" in a GUI libraries.
|
* Sometimes also known as "Kit" in a GUI libraries.
|
||||||
*
|
*
|
||||||
@@ -20,7 +20,7 @@ namespace DesignPatterns\Creational\AbstractFactory;
|
|||||||
abstract class AbstractFactory
|
abstract class AbstractFactory
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Creates a text component
|
* Creates a text component.
|
||||||
*
|
*
|
||||||
* @param string $content
|
* @param string $content
|
||||||
*
|
*
|
||||||
@@ -29,7 +29,7 @@ abstract class AbstractFactory
|
|||||||
abstract public function createText($content);
|
abstract public function createText($content);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a picture component
|
* Creates a picture component.
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
* @param string $name
|
* @param string $name
|
||||||
|
@@ -5,14 +5,14 @@ namespace DesignPatterns\Creational\AbstractFactory\Html;
|
|||||||
use DesignPatterns\Creational\AbstractFactory\Picture as BasePicture;
|
use DesignPatterns\Creational\AbstractFactory\Picture as BasePicture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Picture
|
* Class Picture.
|
||||||
*
|
*
|
||||||
* Picture is a concrete image for HTML rendering
|
* Picture is a concrete image for HTML rendering
|
||||||
*/
|
*/
|
||||||
class Picture extends BasePicture
|
class Picture extends BasePicture
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* some crude rendering from HTML output
|
* some crude rendering from HTML output.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@@ -5,14 +5,14 @@ namespace DesignPatterns\Creational\AbstractFactory\Html;
|
|||||||
use DesignPatterns\Creational\AbstractFactory\Text as BaseText;
|
use DesignPatterns\Creational\AbstractFactory\Text as BaseText;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Text
|
* Class Text.
|
||||||
*
|
*
|
||||||
* Text is a concrete text for HTML rendering
|
* Text is a concrete text for HTML rendering
|
||||||
*/
|
*/
|
||||||
class Text extends BaseText
|
class Text extends BaseText
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* some crude rendering from HTML output
|
* some crude rendering from HTML output.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@@ -3,14 +3,14 @@
|
|||||||
namespace DesignPatterns\Creational\AbstractFactory;
|
namespace DesignPatterns\Creational\AbstractFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class HtmlFactory
|
* Class HtmlFactory.
|
||||||
*
|
*
|
||||||
* HtmlFactory is a concrete factory for HTML component
|
* HtmlFactory is a concrete factory for HTML component
|
||||||
*/
|
*/
|
||||||
class HtmlFactory extends AbstractFactory
|
class HtmlFactory extends AbstractFactory
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Creates a picture component
|
* Creates a picture component.
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
* @param string $name
|
* @param string $name
|
||||||
@@ -23,7 +23,7 @@ class HtmlFactory extends AbstractFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a text component
|
* Creates a text component.
|
||||||
*
|
*
|
||||||
* @param string $content
|
* @param string $content
|
||||||
*
|
*
|
||||||
|
@@ -5,14 +5,14 @@ namespace DesignPatterns\Creational\AbstractFactory\Json;
|
|||||||
use DesignPatterns\Creational\AbstractFactory\Picture as BasePicture;
|
use DesignPatterns\Creational\AbstractFactory\Picture as BasePicture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Picture
|
* Class Picture.
|
||||||
*
|
*
|
||||||
* Picture is a concrete image for JSON rendering
|
* Picture is a concrete image for JSON rendering
|
||||||
*/
|
*/
|
||||||
class Picture extends BasePicture
|
class Picture extends BasePicture
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* some crude rendering from JSON output
|
* some crude rendering from JSON output.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@@ -5,14 +5,14 @@ namespace DesignPatterns\Creational\AbstractFactory\Json;
|
|||||||
use DesignPatterns\Creational\AbstractFactory\Text as BaseText;
|
use DesignPatterns\Creational\AbstractFactory\Text as BaseText;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Text
|
* Class Text.
|
||||||
*
|
*
|
||||||
* Text is a text component with a JSON rendering
|
* Text is a text component with a JSON rendering
|
||||||
*/
|
*/
|
||||||
class Text extends BaseText
|
class Text extends BaseText
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* some crude rendering from JSON output
|
* some crude rendering from JSON output.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@@ -3,16 +3,15 @@
|
|||||||
namespace DesignPatterns\Creational\AbstractFactory;
|
namespace DesignPatterns\Creational\AbstractFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class JsonFactory
|
* Class JsonFactory.
|
||||||
*
|
*
|
||||||
* JsonFactory is a factory for creating a family of JSON component
|
* JsonFactory is a factory for creating a family of JSON component
|
||||||
* (example for ajax)
|
* (example for ajax)
|
||||||
*/
|
*/
|
||||||
class JsonFactory extends AbstractFactory
|
class JsonFactory extends AbstractFactory
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a picture component
|
* Creates a picture component.
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
* @param string $name
|
* @param string $name
|
||||||
@@ -25,7 +24,7 @@ class JsonFactory extends AbstractFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a text component
|
* Creates a text component.
|
||||||
*
|
*
|
||||||
* @param string $content
|
* @param string $content
|
||||||
*
|
*
|
||||||
|
@@ -3,16 +3,15 @@
|
|||||||
namespace DesignPatterns\Creational\AbstractFactory;
|
namespace DesignPatterns\Creational\AbstractFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface MediaInterface
|
* Interface MediaInterface.
|
||||||
*
|
*
|
||||||
* This contract is not part of the pattern, in general case, each component
|
* This contract is not part of the pattern, in general case, each component
|
||||||
* are not related
|
* are not related
|
||||||
*/
|
*/
|
||||||
interface MediaInterface
|
interface MediaInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* some crude rendering from JSON or html output (depended on concrete class)
|
* some crude rendering from JSON or html output (depended on concrete class).
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@@ -3,11 +3,10 @@
|
|||||||
namespace DesignPatterns\Creational\AbstractFactory;
|
namespace DesignPatterns\Creational\AbstractFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Picture
|
* Class Picture.
|
||||||
*/
|
*/
|
||||||
abstract class Picture implements MediaInterface
|
abstract class Picture implements MediaInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
|
@@ -7,7 +7,7 @@ use DesignPatterns\Creational\AbstractFactory\HtmlFactory;
|
|||||||
use DesignPatterns\Creational\AbstractFactory\JsonFactory;
|
use DesignPatterns\Creational\AbstractFactory\JsonFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AbstractFactoryTest tests concrete factories
|
* AbstractFactoryTest tests concrete factories.
|
||||||
*/
|
*/
|
||||||
class AbstractFactoryTest extends \PHPUnit_Framework_TestCase
|
class AbstractFactoryTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
@@ -15,7 +15,7 @@ class AbstractFactoryTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
array(new JsonFactory()),
|
array(new JsonFactory()),
|
||||||
array(new HtmlFactory())
|
array(new HtmlFactory()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ class AbstractFactoryTest extends \PHPUnit_Framework_TestCase
|
|||||||
$article = array(
|
$article = array(
|
||||||
$factory->createText('Lorem Ipsum'),
|
$factory->createText('Lorem Ipsum'),
|
||||||
$factory->createPicture('/image.jpg', 'caption'),
|
$factory->createPicture('/image.jpg', 'caption'),
|
||||||
$factory->createText('footnotes')
|
$factory->createText('footnotes'),
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertContainsOnly('DesignPatterns\Creational\AbstractFactory\MediaInterface', $article);
|
$this->assertContainsOnly('DesignPatterns\Creational\AbstractFactory\MediaInterface', $article);
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Creational\AbstractFactory;
|
namespace DesignPatterns\Creational\AbstractFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Text
|
* Class Text.
|
||||||
*/
|
*/
|
||||||
abstract class Text implements MediaInterface
|
abstract class Text implements MediaInterface
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Creational\Builder;
|
namespace DesignPatterns\Creational\Builder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BikeBuilder builds bike
|
* BikeBuilder builds bike.
|
||||||
*/
|
*/
|
||||||
class BikeBuilder implements BuilderInterface
|
class BikeBuilder implements BuilderInterface
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Creational\Builder;
|
namespace DesignPatterns\Creational\Builder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CarBuilder builds car
|
* CarBuilder builds car.
|
||||||
*/
|
*/
|
||||||
class CarBuilder implements BuilderInterface
|
class CarBuilder implements BuilderInterface
|
||||||
{
|
{
|
||||||
|
@@ -10,9 +10,8 @@ namespace DesignPatterns\Creational\Builder;
|
|||||||
*/
|
*/
|
||||||
class Director
|
class Director
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The director don't know 'bout concrete part
|
* The director don't know about concrete part.
|
||||||
*
|
*
|
||||||
* @param BuilderInterface $builder
|
* @param BuilderInterface $builder
|
||||||
*
|
*
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Creational\Builder\Parts;
|
namespace DesignPatterns\Creational\Builder\Parts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bike is a bike
|
* Bike is a bike.
|
||||||
*/
|
*/
|
||||||
class Bike extends Vehicle
|
class Bike extends Vehicle
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Creational\Builder\Parts;
|
namespace DesignPatterns\Creational\Builder\Parts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Car is a car
|
* Car is a car.
|
||||||
*/
|
*/
|
||||||
class Car extends Vehicle
|
class Car extends Vehicle
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Creational\Builder\Parts;
|
namespace DesignPatterns\Creational\Builder\Parts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Door
|
* Class Door.
|
||||||
*/
|
*/
|
||||||
class Door
|
class Door
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Creational\Builder\Parts;
|
namespace DesignPatterns\Creational\Builder\Parts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Engine
|
* Class Engine.
|
||||||
*/
|
*/
|
||||||
class Engine
|
class Engine
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Creational\Builder\Parts;
|
namespace DesignPatterns\Creational\Builder\Parts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VehicleInterface is a contract for a vehicle
|
* Vehicle class is an abstraction for a vehicle.
|
||||||
*/
|
*/
|
||||||
abstract class Vehicle
|
abstract class Vehicle
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Creational\Builder\Parts;
|
namespace DesignPatterns\Creational\Builder\Parts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Wheel
|
* Class Wheel.
|
||||||
*/
|
*/
|
||||||
class Wheel
|
class Wheel
|
||||||
{
|
{
|
||||||
|
@@ -2,17 +2,16 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Creational\Builder\Tests;
|
namespace DesignPatterns\Creational\Builder\Tests;
|
||||||
|
|
||||||
use DesignPatterns\Creational\Builder\Director;
|
|
||||||
use DesignPatterns\Creational\Builder\CarBuilder;
|
|
||||||
use DesignPatterns\Creational\Builder\BikeBuilder;
|
use DesignPatterns\Creational\Builder\BikeBuilder;
|
||||||
use DesignPatterns\Creational\Builder\BuilderInterface;
|
use DesignPatterns\Creational\Builder\BuilderInterface;
|
||||||
|
use DesignPatterns\Creational\Builder\CarBuilder;
|
||||||
|
use DesignPatterns\Creational\Builder\Director;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DirectorTest tests the builder pattern
|
* DirectorTest tests the builder pattern.
|
||||||
*/
|
*/
|
||||||
class DirectorTest extends \PHPUnit_Framework_TestCase
|
class DirectorTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
protected $director;
|
protected $director;
|
||||||
|
|
||||||
protected function setUp()
|
protected function setUp()
|
||||||
@@ -24,7 +23,7 @@ class DirectorTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
array(new CarBuilder()),
|
array(new CarBuilder()),
|
||||||
array(new BikeBuilder())
|
array(new BikeBuilder()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Creational\FactoryMethod;
|
namespace DesignPatterns\Creational\FactoryMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bicycle is a bicycle
|
* Bicycle is a bicycle.
|
||||||
*/
|
*/
|
||||||
class Bicycle implements VehicleInterface
|
class Bicycle implements VehicleInterface
|
||||||
{
|
{
|
||||||
@@ -13,7 +13,7 @@ class Bicycle implements VehicleInterface
|
|||||||
protected $color;
|
protected $color;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sets the color of the bicycle
|
* sets the color of the bicycle.
|
||||||
*
|
*
|
||||||
* @param string $rgb
|
* @param string $rgb
|
||||||
*/
|
*/
|
||||||
|
@@ -3,16 +3,15 @@
|
|||||||
namespace DesignPatterns\Creational\FactoryMethod;
|
namespace DesignPatterns\Creational\FactoryMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* class FactoryMethod
|
* class FactoryMethod.
|
||||||
*/
|
*/
|
||||||
abstract class FactoryMethod
|
abstract class FactoryMethod
|
||||||
{
|
{
|
||||||
|
|
||||||
const CHEAP = 1;
|
const CHEAP = 1;
|
||||||
const FAST = 2;
|
const FAST = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The children of the class must implement this method
|
* The children of the class must implement this method.
|
||||||
*
|
*
|
||||||
* Sometimes this method can be public to get "raw" object
|
* Sometimes this method can be public to get "raw" object
|
||||||
*
|
*
|
||||||
@@ -23,7 +22,7 @@ abstract class FactoryMethod
|
|||||||
abstract protected function createVehicle($type);
|
abstract protected function createVehicle($type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new vehicle
|
* Creates a new vehicle.
|
||||||
*
|
*
|
||||||
* @param int $type
|
* @param int $type
|
||||||
*
|
*
|
||||||
@@ -32,7 +31,7 @@ abstract class FactoryMethod
|
|||||||
public function create($type)
|
public function create($type)
|
||||||
{
|
{
|
||||||
$obj = $this->createVehicle($type);
|
$obj = $this->createVehicle($type);
|
||||||
$obj->setColor("#f00");
|
$obj->setColor('#f00');
|
||||||
|
|
||||||
return $obj;
|
return $obj;
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Creational\FactoryMethod;
|
namespace DesignPatterns\Creational\FactoryMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ferrari is a italian car
|
* Ferrari is a italian car.
|
||||||
*/
|
*/
|
||||||
class Ferrari implements VehicleInterface
|
class Ferrari implements VehicleInterface
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Creational\FactoryMethod;
|
namespace DesignPatterns\Creational\FactoryMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GermanFactory is a vehicle factory in Germany
|
* GermanFactory is a vehicle factory in Germany.
|
||||||
*/
|
*/
|
||||||
class GermanFactory extends FactoryMethod
|
class GermanFactory extends FactoryMethod
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Creational\FactoryMethod;
|
namespace DesignPatterns\Creational\FactoryMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ItalianFactory is vehicle factory in Italy
|
* ItalianFactory is vehicle factory in Italy.
|
||||||
*/
|
*/
|
||||||
class ItalianFactory extends FactoryMethod
|
class ItalianFactory extends FactoryMethod
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Creational\FactoryMethod;
|
namespace DesignPatterns\Creational\FactoryMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Porsche is a german car
|
* Porsche is a german car.
|
||||||
*/
|
*/
|
||||||
class Porsche implements VehicleInterface
|
class Porsche implements VehicleInterface
|
||||||
{
|
{
|
||||||
|
@@ -7,21 +7,20 @@ use DesignPatterns\Creational\FactoryMethod\GermanFactory;
|
|||||||
use DesignPatterns\Creational\FactoryMethod\ItalianFactory;
|
use DesignPatterns\Creational\FactoryMethod\ItalianFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FactoryMethodTest tests the factory method pattern
|
* FactoryMethodTest tests the factory method pattern.
|
||||||
*/
|
*/
|
||||||
class FactoryMethodTest extends \PHPUnit_Framework_TestCase
|
class FactoryMethodTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
protected $type = array(
|
protected $type = array(
|
||||||
FactoryMethod::CHEAP,
|
FactoryMethod::CHEAP,
|
||||||
FactoryMethod::FAST
|
FactoryMethod::FAST,
|
||||||
);
|
);
|
||||||
|
|
||||||
public function getShop()
|
public function getShop()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
array(new GermanFactory()),
|
array(new GermanFactory()),
|
||||||
array(new ItalianFactory())
|
array(new ItalianFactory()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,12 +3,12 @@
|
|||||||
namespace DesignPatterns\Creational\FactoryMethod;
|
namespace DesignPatterns\Creational\FactoryMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VehicleInterface is a contract for a vehicle
|
* VehicleInterface is a contract for a vehicle.
|
||||||
*/
|
*/
|
||||||
interface VehicleInterface
|
interface VehicleInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* sets the color of the vehicle
|
* sets the color of the vehicle.
|
||||||
*
|
*
|
||||||
* @param string $rgb
|
* @param string $rgb
|
||||||
*/
|
*/
|
||||||
|
@@ -3,24 +3,22 @@
|
|||||||
namespace DesignPatterns\Creational\Multiton;
|
namespace DesignPatterns\Creational\Multiton;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* class Multiton
|
* class Multiton.
|
||||||
*/
|
*/
|
||||||
class Multiton
|
class Multiton
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
*
|
* the first instance.
|
||||||
* the first instance
|
|
||||||
*/
|
*/
|
||||||
const INSTANCE_1 = '1';
|
const INSTANCE_1 = '1';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* the second instance.
|
||||||
* the second instance
|
|
||||||
*/
|
*/
|
||||||
const INSTANCE_2 = '2';
|
const INSTANCE_2 = '2';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* holds the named instances
|
* holds the named instances.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
@@ -28,7 +26,6 @@ class Multiton
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* should not be called from outside: private!
|
* should not be called from outside: private!
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
private function __construct()
|
private function __construct()
|
||||||
{
|
{
|
||||||
@@ -36,7 +33,7 @@ class Multiton
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* gets the instance with the given name, e.g. Multiton::INSTANCE_1
|
* gets the instance with the given name, e.g. Multiton::INSTANCE_1
|
||||||
* uses lazy initialization
|
* uses lazy initialization.
|
||||||
*
|
*
|
||||||
* @param string $instanceName
|
* @param string $instanceName
|
||||||
*
|
*
|
||||||
@@ -52,7 +49,7 @@ class Multiton
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* prevent instance from being cloned
|
* prevent instance from being cloned.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
@@ -61,7 +58,7 @@ class Multiton
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* prevent instance from being unserialized
|
* prevent instance from being unserialized.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
@@ -4,7 +4,6 @@ namespace DesignPatterns\Creational\Pool;
|
|||||||
|
|
||||||
class Pool
|
class Pool
|
||||||
{
|
{
|
||||||
|
|
||||||
private $instances = array();
|
private $instances = array();
|
||||||
private $class;
|
private $class;
|
||||||
|
|
||||||
|
@@ -4,11 +4,10 @@ namespace DesignPatterns\Creational\Pool;
|
|||||||
|
|
||||||
class Processor
|
class Processor
|
||||||
{
|
{
|
||||||
|
|
||||||
private $pool;
|
private $pool;
|
||||||
private $processing = 0;
|
private $processing = 0;
|
||||||
private $maxProcesses = 3;
|
private $maxProcesses = 3;
|
||||||
private $waitingQueue = [];
|
private $waitingQueue = array();
|
||||||
|
|
||||||
public function __construct(Pool $pool)
|
public function __construct(Pool $pool)
|
||||||
{
|
{
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user