mirror of
https://github.com/DesignPatternsPHP/DesignPatternsPHP.git
synced 2025-07-28 02:30:20 +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/
|
||||
_build/
|
||||
*.mo
|
||||
.vagrant/
|
||||
phpunit.xml
|
||||
composer.phar
|
||||
|
@@ -20,8 +20,11 @@ cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache
|
||||
|
||||
before_script:
|
||||
before_install:
|
||||
- composer self-update
|
||||
- composer validate
|
||||
|
||||
install:
|
||||
- composer install --prefer-dist --no-interaction
|
||||
|
||||
script:
|
||||
|
@@ -3,7 +3,7 @@
|
||||
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
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
@@ -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
|
||||
*
|
||||
|
@@ -6,7 +6,7 @@ use DesignPatterns\Behavioral\ChainOfResponsibilities\Handler;
|
||||
use DesignPatterns\Behavioral\ChainOfResponsibilities\Request;
|
||||
|
||||
/**
|
||||
* Class FastStorage
|
||||
* Class FastStorage.
|
||||
*/
|
||||
class FastStorage extends Handler
|
||||
{
|
||||
|
@@ -6,14 +6,13 @@ use DesignPatterns\Behavioral\ChainOfResponsibilities\Handler;
|
||||
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
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
class SlowStorage extends Handler
|
||||
{
|
||||
|
@@ -3,16 +3,15 @@
|
||||
namespace DesignPatterns\Behavioral\ChainOfResponsibilities\Tests;
|
||||
|
||||
use DesignPatterns\Behavioral\ChainOfResponsibilities\Request;
|
||||
use DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible;
|
||||
use DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\FastStorage;
|
||||
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
|
||||
{
|
||||
|
||||
/**
|
||||
* @var FastStorage
|
||||
*/
|
||||
@@ -30,7 +29,7 @@ class ChainTest extends \PHPUnit_Framework_TestCase
|
||||
$request->verb = 'get';
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* class CommandInterface
|
||||
* class CommandInterface.
|
||||
*/
|
||||
interface CommandInterface
|
||||
{
|
||||
|
@@ -4,7 +4,7 @@ namespace DesignPatterns\Behavioral\Command;
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
@@ -14,8 +14,8 @@ class HelloCommand implements CommandInterface
|
||||
protected $output;
|
||||
|
||||
/**
|
||||
* Each concrete command is builded with different receivers.
|
||||
* Can be one, many, none or even other Command in parameters
|
||||
* 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
|
||||
*/
|
||||
@@ -25,7 +25,7 @@ class HelloCommand implements CommandInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* execute and output "Hello World"
|
||||
* execute and output "Hello World".
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
|
@@ -4,7 +4,7 @@ namespace DesignPatterns\Behavioral\Command;
|
||||
|
||||
/**
|
||||
* Invoker is using the command given to it.
|
||||
* Example : an Application in SF2
|
||||
* Example : an Application in SF2.
|
||||
*/
|
||||
class Invoker
|
||||
{
|
||||
@@ -25,7 +25,7 @@ class Invoker
|
||||
}
|
||||
|
||||
/**
|
||||
* executes the command
|
||||
* executes the command.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
|
@@ -3,15 +3,44 @@
|
||||
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
|
||||
{
|
||||
private $enableDate = false;
|
||||
|
||||
private $output = array();
|
||||
|
||||
/**
|
||||
* @param string $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;
|
||||
|
||||
use DesignPatterns\Behavioral\Command\HelloCommand;
|
||||
use DesignPatterns\Behavioral\Command\Invoker;
|
||||
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
|
||||
{
|
||||
|
||||
/**
|
||||
* @var Invoker
|
||||
*/
|
||||
@@ -31,7 +30,7 @@ class CommandTest extends \PHPUnit_Framework_TestCase
|
||||
public function testInvocation()
|
||||
{
|
||||
$this->invoker->setCommand(new HelloCommand($this->receiver));
|
||||
$this->expectOutputString('Hello World');
|
||||
$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
|
||||
{
|
||||
|
||||
private $author;
|
||||
|
||||
private $title;
|
||||
@@ -27,6 +26,6 @@ class Book
|
||||
|
||||
public function getAuthorAndTitle()
|
||||
{
|
||||
return $this->getTitle() . ' by ' . $this->getAuthor();
|
||||
return $this->getTitle().' by '.$this->getAuthor();
|
||||
}
|
||||
}
|
||||
|
@@ -4,23 +4,20 @@ namespace DesignPatterns\Behavioral\Iterator;
|
||||
|
||||
class BookList implements \Countable
|
||||
{
|
||||
|
||||
private $books;
|
||||
|
||||
public function getBook($bookNumberToGet)
|
||||
{
|
||||
if ((int)$bookNumberToGet <= $this->count()) {
|
||||
if (isset($this->books[$bookNumberToGet])) {
|
||||
return $this->books[$bookNumberToGet];
|
||||
}
|
||||
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
public function addBook(Book $book)
|
||||
{
|
||||
$this->books[] = $book;
|
||||
|
||||
return $this->count();
|
||||
}
|
||||
|
||||
public function removeBook(Book $bookToRemove)
|
||||
@@ -31,8 +28,6 @@ class BookList implements \Countable
|
||||
unset($this->books[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->count();
|
||||
}
|
||||
|
||||
public function count()
|
||||
|
@@ -4,11 +4,10 @@ namespace DesignPatterns\Behavioral\Iterator;
|
||||
|
||||
class BookListIterator implements \Iterator
|
||||
{
|
||||
|
||||
/**
|
||||
* @var BookList
|
||||
*/
|
||||
protected $bookList;
|
||||
private $bookList;
|
||||
|
||||
/**
|
||||
* @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
|
||||
*
|
||||
* @return Book Can return any type.
|
||||
*/
|
||||
public function current()
|
||||
@@ -32,8 +33,10 @@ class BookListIterator implements \Iterator
|
||||
|
||||
/**
|
||||
* (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
|
||||
*
|
||||
* @return void Any returned value is ignored.
|
||||
*/
|
||||
public function next()
|
||||
@@ -43,8 +46,10 @@ class BookListIterator implements \Iterator
|
||||
|
||||
/**
|
||||
* (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
|
||||
*
|
||||
* @return mixed scalar on success, or null on failure.
|
||||
*/
|
||||
public function key()
|
||||
@@ -54,20 +59,24 @@ class BookListIterator implements \Iterator
|
||||
|
||||
/**
|
||||
* (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
|
||||
* @return boolean The return value will be casted to boolean and then evaluated.
|
||||
* Returns true on success or false on failure.
|
||||
*
|
||||
* @return bool The return value will be casted to boolean and then evaluated.
|
||||
* Returns true on success or false on failure.
|
||||
*/
|
||||
public function valid()
|
||||
{
|
||||
return $this->currentBook < $this->bookList->count();
|
||||
return null !== $this->bookList->getBook($this->currentBook);
|
||||
}
|
||||
|
||||
/**
|
||||
* (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
|
||||
*
|
||||
* @return void Any returned value is ignored.
|
||||
*/
|
||||
public function rewind()
|
||||
|
@@ -2,8 +2,17 @@
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -11,13 +20,68 @@ class BookListReverseIterator extends BookListIterator
|
||||
$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()
|
||||
{
|
||||
$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()
|
||||
{
|
||||
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
|
||||
{
|
||||
|
||||
/**
|
||||
* @var BookList
|
||||
*/
|
||||
@@ -30,8 +29,8 @@ class IteratorTest extends \PHPUnit_Framework_TestCase
|
||||
array(
|
||||
'Learning PHP Design Patterns by William Sanders',
|
||||
'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()
|
||||
{
|
||||
|
@@ -9,12 +9,12 @@ namespace DesignPatterns\Behavioral\Mediator;
|
||||
abstract class Colleague
|
||||
{
|
||||
/**
|
||||
* this ensures no change in subclasses
|
||||
* this ensures no change in subclasses.
|
||||
*
|
||||
* @var MediatorInterface
|
||||
*/
|
||||
private $mediator;
|
||||
|
||||
|
||||
/**
|
||||
* @param MediatorInterface $medium
|
||||
*/
|
||||
@@ -25,6 +25,7 @@ abstract class Colleague
|
||||
}
|
||||
|
||||
// for subclasses
|
||||
|
||||
protected function getMediator()
|
||||
{
|
||||
return $this->mediator;
|
||||
|
@@ -2,15 +2,12 @@
|
||||
|
||||
namespace DesignPatterns\Behavioral\Mediator;
|
||||
|
||||
use DesignPatterns\Behavioral\Mediator\Subsystem;
|
||||
|
||||
/**
|
||||
* Mediator is the concrete Mediator for this design pattern.
|
||||
* In this example, I have made a "Hello World" with the Mediator Pattern.
|
||||
*/
|
||||
class Mediator implements MediatorInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @var Subsystem\Server
|
||||
*/
|
||||
@@ -39,7 +36,7 @@ class Mediator implements MediatorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* make request
|
||||
* make request.
|
||||
*/
|
||||
public function makeRequest()
|
||||
{
|
||||
@@ -47,7 +44,8 @@ class Mediator implements MediatorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* query db
|
||||
* query db.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function queryDb()
|
||||
@@ -56,7 +54,7 @@ class Mediator implements MediatorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* send response
|
||||
* send response.
|
||||
*
|
||||
* @param string $content
|
||||
*/
|
||||
|
@@ -4,24 +4,24 @@ namespace DesignPatterns\Behavioral\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
|
||||
{
|
||||
/**
|
||||
* sends the response
|
||||
* sends the response.
|
||||
*
|
||||
* @param string $content
|
||||
*/
|
||||
public function sendResponse($content);
|
||||
|
||||
/**
|
||||
* makes a request
|
||||
* makes a request.
|
||||
*/
|
||||
public function makeRequest();
|
||||
|
||||
/**
|
||||
* queries the DB
|
||||
* queries the DB.
|
||||
*/
|
||||
public function queryDb();
|
||||
}
|
||||
|
@@ -4,8 +4,8 @@
|
||||
Purpose
|
||||
-------
|
||||
|
||||
This pattern provides an easy to decouple many components working
|
||||
together. It is a good alternative over Observer IF you have a "central
|
||||
This pattern provides an easy way to decouple many components working
|
||||
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).
|
||||
|
||||
All components (called Colleague) are only coupled to the
|
||||
@@ -70,4 +70,4 @@ Tests/MediatorTest.php
|
||||
:linenos:
|
||||
|
||||
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Behavioral/Mediator
|
||||
.. __: http://en.wikipedia.org/wiki/Mediator_pattern
|
||||
.. __: http://en.wikipedia.org/wiki/Mediator_pattern
|
||||
|
@@ -5,12 +5,12 @@ namespace DesignPatterns\Behavioral\Mediator\Subsystem;
|
||||
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
|
||||
{
|
||||
/**
|
||||
* request
|
||||
* request.
|
||||
*/
|
||||
public function request()
|
||||
{
|
||||
@@ -18,7 +18,7 @@ class Client extends Colleague
|
||||
}
|
||||
|
||||
/**
|
||||
* output content
|
||||
* output content.
|
||||
*
|
||||
* @param string $content
|
||||
*/
|
||||
|
@@ -5,7 +5,7 @@ namespace DesignPatterns\Behavioral\Mediator\Subsystem;
|
||||
use DesignPatterns\Behavioral\Mediator\Colleague;
|
||||
|
||||
/**
|
||||
* Database is a database service
|
||||
* Database is a database service.
|
||||
*/
|
||||
class Database extends Colleague
|
||||
{
|
||||
@@ -14,6 +14,6 @@ class Database extends Colleague
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
return "World";
|
||||
return 'World';
|
||||
}
|
||||
}
|
||||
|
@@ -5,12 +5,12 @@ namespace DesignPatterns\Behavioral\Mediator\Subsystem;
|
||||
use DesignPatterns\Behavioral\Mediator\Colleague;
|
||||
|
||||
/**
|
||||
* Server serves responses
|
||||
* Server serves responses.
|
||||
*/
|
||||
class Server extends Colleague
|
||||
{
|
||||
/**
|
||||
* process on server
|
||||
* process on server.
|
||||
*/
|
||||
public function process()
|
||||
{
|
||||
|
@@ -3,16 +3,15 @@
|
||||
namespace DesignPatterns\Tests\Mediator\Tests;
|
||||
|
||||
use DesignPatterns\Behavioral\Mediator\Mediator;
|
||||
use DesignPatterns\Behavioral\Mediator\Subsystem\Database;
|
||||
use DesignPatterns\Behavioral\Mediator\Subsystem\Client;
|
||||
use DesignPatterns\Behavioral\Mediator\Subsystem\Database;
|
||||
use DesignPatterns\Behavioral\Mediator\Subsystem\Server;
|
||||
|
||||
/**
|
||||
* MediatorTest tests hello world
|
||||
* MediatorTest tests hello world.
|
||||
*/
|
||||
class MediatorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
protected $client;
|
||||
|
||||
protected function setUp()
|
||||
|
@@ -4,30 +4,46 @@ namespace DesignPatterns\Behavioral\Memento;
|
||||
|
||||
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();
|
||||
|
||||
//Setting state to State1
|
||||
$originator->setState("State1");
|
||||
$originator->setState('State1');
|
||||
//Setting state to State2
|
||||
$originator->setState("State2");
|
||||
$originator->setState('State2');
|
||||
//Saving State2 to Memento
|
||||
$savedStates[] = $originator->saveToMemento();
|
||||
$this->saveToHistory($originator->getStateAsMemento());
|
||||
//Setting state to State3
|
||||
$originator->setState("State3");
|
||||
$originator->setState('State3');
|
||||
|
||||
// We can request multiple mementos, and choose which one to roll back to.
|
||||
// Saving State3 to Memento
|
||||
$savedStates[] = $originator->saveToMemento();
|
||||
$this->saveToHistory($originator->getStateAsMemento());
|
||||
//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
|
||||
|
||||
return $originator->getStateAsMemento()->getState();
|
||||
}
|
||||
}
|
||||
|
@@ -15,14 +15,17 @@ class Originator
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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;
|
||||
|
||||
return new Memento($state);
|
||||
|
@@ -4,26 +4,43 @@
|
||||
Purpose
|
||||
-------
|
||||
|
||||
Provide the ability to restore an object to its previous state (undo via
|
||||
rollback).
|
||||
It provides the ability to restore an object to it's previous state (undo
|
||||
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
|
||||
caretaker and a memento. The originator is some object that has an
|
||||
internal state. The caretaker is going to do something to the
|
||||
originator, but wants to be able to undo the change. The caretaker first
|
||||
asks the originator for a memento object. Then it does whatever
|
||||
operation (or sequence of operations) it was going to do. To roll back
|
||||
to the state before the operations, it returns the memento object to the
|
||||
originator. The memento object itself is an opaque object (one which the
|
||||
caretaker cannot, or should not, change). When using this pattern, care
|
||||
should be taken if the originator may change other objects or resources
|
||||
- the memento pattern operates on a single object.
|
||||
The memento pattern is implemented with three objects: the Originator, a
|
||||
Caretaker and a Memento.
|
||||
|
||||
Memento – an object that *contains a concrete unique snapshot of state* of
|
||||
any object or resource: string, number, array, an instance of class and so on.
|
||||
The uniqueness in this case does not imply the prohibition existence of similar
|
||||
states in different snapshots. That means the state can be extracted as
|
||||
the independent clone. Any object stored in the Memento should be
|
||||
*a full copy of the original object rather than a reference* to the original
|
||||
object. The Memento object is a "opaque object" (the object that no one can
|
||||
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
|
||||
--------
|
||||
|
||||
- The seed of a pseudorandom number generator
|
||||
- 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
|
||||
-----------
|
||||
|
@@ -2,68 +2,161 @@
|
||||
|
||||
namespace DesignPatterns\Behavioral\Memento\Tests;
|
||||
|
||||
use DesignPatterns\Behavioral\Memento\Caretaker;
|
||||
use DesignPatterns\Behavioral\Memento\Memento;
|
||||
use DesignPatterns\Behavioral\Memento\Originator;
|
||||
|
||||
/**
|
||||
* MementoTest tests the memento pattern
|
||||
* MementoTest tests the memento pattern.
|
||||
*/
|
||||
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()
|
||||
{
|
||||
$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->setState("State3");
|
||||
|
||||
$this->assertAttributeEquals("State3", "state", $originator);
|
||||
|
||||
$originator->restoreFromMemento($savedState);
|
||||
|
||||
$this->assertAttributeEquals("State2", "state", $originator);
|
||||
$originator->restoreFromMemento($snapshot);
|
||||
$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();
|
||||
|
||||
$foo = new \stdClass();
|
||||
$foo->data = "foo";
|
||||
$first = new \stdClass();
|
||||
$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();
|
||||
$bar->data = "bar";
|
||||
public function testCaretaker()
|
||||
{
|
||||
$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);
|
||||
|
||||
$this->assertAttributeEquals($bar, "state", $originator);
|
||||
|
||||
$originator->restoreFromMemento($savedState);
|
||||
|
||||
$this->assertAttributeEquals($foo, "state", $originator);
|
||||
|
||||
$foo->data = null;
|
||||
|
||||
$this->assertAttributeNotEquals($foo, "state", $savedState);
|
||||
|
||||
$this->assertAttributeNotEquals($foo, "state", $originator);
|
||||
public function testCaretakerCustomLogic()
|
||||
{
|
||||
$caretaker = new Caretaker();
|
||||
$result = $caretaker->runCustomLogic();
|
||||
$this->assertEquals('State3', $result);
|
||||
}
|
||||
}
|
||||
|
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;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
@@ -3,7 +3,7 @@
|
||||
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
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Behavioral\NullObject;
|
||||
|
||||
/**
|
||||
* Service is dummy service that uses a logger
|
||||
* Service is dummy service that uses a logger.
|
||||
*/
|
||||
class Service
|
||||
{
|
||||
@@ -13,7 +13,7 @@ class Service
|
||||
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
|
||||
*/
|
||||
@@ -28,7 +28,7 @@ class Service
|
||||
public function doSomething()
|
||||
{
|
||||
// no more check "if (!is_null($this->logger))..." with the NullObject pattern
|
||||
$this->logger->log('We are in ' . __METHOD__);
|
||||
$this->logger->log('We are in '.__METHOD__);
|
||||
// something to do...
|
||||
}
|
||||
}
|
||||
|
@@ -3,15 +3,14 @@
|
||||
namespace DesignPatterns\Behavioral\NullObject\Tests;
|
||||
|
||||
use DesignPatterns\Behavioral\NullObject\NullLogger;
|
||||
use DesignPatterns\Behavioral\NullObject\Service;
|
||||
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
|
||||
{
|
||||
|
||||
public function testNullObject()
|
||||
{
|
||||
// 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;
|
||||
|
||||
use DesignPatterns\Behavioral\Observer\UserObserver;
|
||||
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
|
||||
{
|
||||
|
||||
protected $observer;
|
||||
|
||||
protected function setUp()
|
||||
@@ -19,7 +18,7 @@ class ObserverTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the notification
|
||||
* Tests the notification.
|
||||
*/
|
||||
public function testNotify()
|
||||
{
|
||||
@@ -31,7 +30,7 @@ class ObserverTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the subscribing
|
||||
* Tests the subscribing.
|
||||
*/
|
||||
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()
|
||||
{
|
||||
|
@@ -3,34 +3,33 @@
|
||||
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.
|
||||
*
|
||||
*/
|
||||
class User implements \SplSubject
|
||||
{
|
||||
/**
|
||||
* user data
|
||||
* user data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $data = array();
|
||||
|
||||
/**
|
||||
* observers
|
||||
* observers.
|
||||
*
|
||||
* @var \SplObjectStorage
|
||||
*/
|
||||
protected $observers;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->observers = new \SplObjectStorage();
|
||||
}
|
||||
|
||||
/**
|
||||
* attach a new observer
|
||||
* attach a new observer.
|
||||
*
|
||||
* @param \SplObserver $observer
|
||||
*
|
||||
@@ -42,7 +41,7 @@ class User implements \SplSubject
|
||||
}
|
||||
|
||||
/**
|
||||
* detach an observer
|
||||
* detach an observer.
|
||||
*
|
||||
* @param \SplObserver $observer
|
||||
*
|
||||
@@ -54,7 +53,7 @@ class User implements \SplSubject
|
||||
}
|
||||
|
||||
/**
|
||||
* notify observers
|
||||
* notify observers.
|
||||
*
|
||||
* @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()
|
||||
* on attributes that matter when changed
|
||||
* on attributes that matter when changed.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
|
@@ -3,18 +3,18 @@
|
||||
namespace DesignPatterns\Behavioral\Observer;
|
||||
|
||||
/**
|
||||
* class UserObserver
|
||||
* class UserObserver.
|
||||
*/
|
||||
class UserObserver implements \SplObserver
|
||||
{
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public function update(\SplSubject $subject)
|
||||
{
|
||||
echo get_class($subject) . ' has been updated';
|
||||
echo get_class($subject).' has been updated';
|
||||
}
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@ communication.
|
||||
* [Command](Command) [:notebook:](http://en.wikipedia.org/wiki/Command_pattern)
|
||||
* [Iterator](Iterator) [:notebook:](http://en.wikipedia.org/wiki/Iterator_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)
|
||||
* [Observer](Observer) [:notebook:](http://en.wikipedia.org/wiki/Observer_pattern)
|
||||
* [Specification](Specification) [:notebook:](http://en.wikipedia.org/wiki/Specification_pattern)
|
||||
|
@@ -1,13 +1,14 @@
|
||||
<?php
|
||||
|
||||
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
|
||||
{
|
||||
/**
|
||||
* Checks if given item meets all criteria
|
||||
* Checks if given item meets all criteria.
|
||||
*
|
||||
* @param Item $item
|
||||
*
|
||||
@@ -16,7 +17,7 @@ abstract class AbstractSpecification implements SpecificationInterface
|
||||
abstract public function isSatisfiedBy(Item $item);
|
||||
|
||||
/**
|
||||
* Creates a new logical AND specification
|
||||
* Creates a new logical AND specification.
|
||||
*
|
||||
* @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
|
||||
*
|
||||
@@ -40,7 +41,7 @@ abstract class AbstractSpecification implements SpecificationInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new logical NOT specification
|
||||
* Creates a new logical NOT specification.
|
||||
*
|
||||
* @return SpecificationInterface
|
||||
*/
|
||||
|
@@ -1,17 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Behavioral\Specification;
|
||||
|
||||
/**
|
||||
* A logical OR specification
|
||||
* A logical OR specification.
|
||||
*/
|
||||
class Either extends AbstractSpecification
|
||||
{
|
||||
|
||||
protected $left;
|
||||
protected $right;
|
||||
|
||||
/**
|
||||
* A composite wrapper of two specifications
|
||||
* A composite wrapper of two specifications.
|
||||
*
|
||||
* @param SpecificationInterface $left
|
||||
* @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
|
||||
*
|
||||
|
@@ -1,15 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Behavioral\Specification;
|
||||
|
||||
/**
|
||||
* An trivial item
|
||||
* An trivial item.
|
||||
*/
|
||||
class Item
|
||||
{
|
||||
protected $price;
|
||||
|
||||
/**
|
||||
* An item must have a price
|
||||
* An item must have a price.
|
||||
*
|
||||
* @param int $price
|
||||
*/
|
||||
@@ -19,7 +20,7 @@ class Item
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the items price
|
||||
* Get the items price.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
|
@@ -1,16 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Behavioral\Specification;
|
||||
|
||||
/**
|
||||
* A logical Not specification
|
||||
* A logical Not specification.
|
||||
*/
|
||||
class Not extends AbstractSpecification
|
||||
{
|
||||
|
||||
protected $spec;
|
||||
|
||||
/**
|
||||
* Creates a new specification wrapping another
|
||||
* Creates a new specification wrapping another.
|
||||
*
|
||||
* @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
|
||||
*
|
||||
|
@@ -1,17 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Behavioral\Specification;
|
||||
|
||||
/**
|
||||
* A logical AND specification
|
||||
* A logical AND specification.
|
||||
*/
|
||||
class Plus extends AbstractSpecification
|
||||
{
|
||||
|
||||
protected $left;
|
||||
protected $right;
|
||||
|
||||
/**
|
||||
* Creation of a logical AND of two specifications
|
||||
* Creation of a logical AND of two specifications.
|
||||
*
|
||||
* @param SpecificationInterface $left
|
||||
* @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
|
||||
*
|
||||
|
@@ -1,8 +1,9 @@
|
||||
<?php
|
||||
|
||||
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
|
||||
{
|
||||
@@ -10,7 +11,7 @@ class PriceSpecification extends AbstractSpecification
|
||||
protected $minPrice;
|
||||
|
||||
/**
|
||||
* Sets the optional maximum price
|
||||
* Sets the optional maximum price.
|
||||
*
|
||||
* @param int $maxPrice
|
||||
*/
|
||||
@@ -20,7 +21,7 @@ class PriceSpecification extends AbstractSpecification
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the optional minimum price
|
||||
* Sets the optional minimum price.
|
||||
*
|
||||
* @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
|
||||
*
|
||||
|
@@ -1,13 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Behavioral\Specification;
|
||||
|
||||
/**
|
||||
* An interface for a specification
|
||||
* An interface for a specification.
|
||||
*/
|
||||
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
|
||||
*
|
||||
@@ -16,21 +17,21 @@ interface SpecificationInterface
|
||||
public function isSatisfiedBy(Item $item);
|
||||
|
||||
/**
|
||||
* Creates a logical AND specification
|
||||
* Creates a logical AND specification.
|
||||
*
|
||||
* @param SpecificationInterface $spec
|
||||
*/
|
||||
public function plus(SpecificationInterface $spec);
|
||||
|
||||
/**
|
||||
* Creates a logical OR specification
|
||||
* Creates a logical OR specification.
|
||||
*
|
||||
* @param SpecificationInterface $spec
|
||||
*/
|
||||
public function either(SpecificationInterface $spec);
|
||||
|
||||
/**
|
||||
* Creates a logical not specification
|
||||
* Creates a logical not specification.
|
||||
*/
|
||||
public function not();
|
||||
}
|
||||
|
@@ -2,11 +2,11 @@
|
||||
|
||||
namespace DesignPatterns\Behavioral\Specification\Tests;
|
||||
|
||||
use DesignPatterns\Behavioral\Specification\PriceSpecification;
|
||||
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
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Behavioral\State;
|
||||
|
||||
/**
|
||||
* Class CreateOrder
|
||||
* Class CreateOrder.
|
||||
*/
|
||||
class CreateOrder implements OrderInterface
|
||||
{
|
||||
@@ -38,8 +38,9 @@ class CreateOrder implements OrderInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed|void
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function completeOrder()
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Behavioral\State;
|
||||
|
||||
/**
|
||||
* Class OrderController
|
||||
* Class OrderController.
|
||||
*/
|
||||
class OrderController
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Behavioral\State;
|
||||
|
||||
/**
|
||||
* Class OrderFactory
|
||||
* Class OrderFactory.
|
||||
*/
|
||||
class OrderFactory
|
||||
{
|
||||
@@ -15,8 +15,9 @@ class OrderFactory
|
||||
/**
|
||||
* @param int $id
|
||||
*
|
||||
* @return CreateOrder|ShippingOrder
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return CreateOrder|ShippingOrder
|
||||
*/
|
||||
public static function getOrder($id)
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Behavioral\State;
|
||||
|
||||
/**
|
||||
* Class OrderInterface
|
||||
* Class OrderInterface.
|
||||
*/
|
||||
interface OrderInterface
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Behavioral\State;
|
||||
|
||||
/**
|
||||
* Class ShippingOrder
|
||||
* Class ShippingOrder.
|
||||
*/
|
||||
class ShippingOrder implements OrderInterface
|
||||
{
|
||||
@@ -26,8 +26,9 @@ class ShippingOrder implements OrderInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed|void
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function shipOrder()
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Behavioral\Strategy;
|
||||
|
||||
/**
|
||||
* Class ComparatorInterface
|
||||
* Class ComparatorInterface.
|
||||
*/
|
||||
interface ComparatorInterface
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Behavioral\Strategy;
|
||||
|
||||
/**
|
||||
* Class DateComparator
|
||||
* Class DateComparator.
|
||||
*/
|
||||
class DateComparator implements ComparatorInterface
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Behavioral\Strategy;
|
||||
|
||||
/**
|
||||
* Class IdComparator
|
||||
* Class IdComparator.
|
||||
*/
|
||||
class IdComparator implements ComparatorInterface
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Behavioral\Strategy;
|
||||
|
||||
/**
|
||||
* Class ObjectCollection
|
||||
* Class ObjectCollection.
|
||||
*/
|
||||
class ObjectCollection
|
||||
{
|
||||
@@ -31,7 +31,7 @@ class ObjectCollection
|
||||
public function sort()
|
||||
{
|
||||
if (!$this->comparator) {
|
||||
throw new \LogicException("Comparator is not set");
|
||||
throw new \LogicException('Comparator is not set');
|
||||
}
|
||||
|
||||
$callback = array($this->comparator, 'compare');
|
||||
|
@@ -8,21 +8,20 @@ use DesignPatterns\Behavioral\Strategy\ObjectCollection;
|
||||
use DesignPatterns\Behavioral\Strategy\Strategy;
|
||||
|
||||
/**
|
||||
* Tests for Strategy pattern
|
||||
* Tests for Strategy pattern.
|
||||
*/
|
||||
class StrategyTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
public function getIdCollection()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
array(array('id' => 2), array('id' => 1), array('id' => 3)),
|
||||
array('id' => 1)
|
||||
array('id' => 1),
|
||||
),
|
||||
array(
|
||||
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(
|
||||
array(
|
||||
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('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;
|
||||
|
||||
/**
|
||||
* BeachJourney is vacation at the beach
|
||||
* BeachJourney is vacation at the beach.
|
||||
*/
|
||||
class BeachJourney extends Journey
|
||||
{
|
||||
/**
|
||||
* prints what to do to enjoy your vacation
|
||||
* prints what to do to enjoy your vacation.
|
||||
*/
|
||||
protected function enjoyVacation()
|
||||
{
|
||||
|
@@ -3,12 +3,12 @@
|
||||
namespace DesignPatterns\Behavioral\TemplateMethod;
|
||||
|
||||
/**
|
||||
* CityJourney is a journey in a city
|
||||
* CityJourney is a journey in a city.
|
||||
*/
|
||||
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()
|
||||
{
|
||||
|
@@ -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();
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
@@ -46,7 +46,7 @@ abstract class Journey
|
||||
|
||||
/**
|
||||
* 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()
|
||||
{
|
||||
|
@@ -5,11 +5,10 @@ namespace DesignPatterns\Behavioral\TemplateMethod\Tests;
|
||||
use DesignPatterns\Behavioral\TemplateMethod;
|
||||
|
||||
/**
|
||||
* JourneyTest tests all journeys
|
||||
* JourneyTest tests all journeys.
|
||||
*/
|
||||
class JourneyTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
public function testBeach()
|
||||
{
|
||||
$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()
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Behavioral\Visitor;
|
||||
|
||||
/**
|
||||
* An example of a Visitor: Group
|
||||
* An example of a Visitor: Group.
|
||||
*/
|
||||
class Group extends Role
|
||||
{
|
||||
@@ -25,6 +25,6 @@ class Group extends Role
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return "Group: " . $this->name;
|
||||
return 'Group: '.$this->name;
|
||||
}
|
||||
}
|
||||
|
@@ -3,12 +3,12 @@
|
||||
namespace DesignPatterns\Behavioral\Visitor;
|
||||
|
||||
/**
|
||||
* class Role
|
||||
* 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
|
||||
*
|
||||
@@ -21,10 +21,10 @@ abstract class Role
|
||||
// this trick to simulate double-dispatch based on type-hinting
|
||||
$klass = get_called_class();
|
||||
preg_match('#([^\\\\]+)$#', $klass, $extract);
|
||||
$visitingMethod = 'visit' . $extract[1];
|
||||
$visitingMethod = 'visit'.$extract[1];
|
||||
|
||||
// this ensures strong typing with visitor interface, not some visitor objects
|
||||
if (!method_exists(__NAMESPACE__ . '\RoleVisitorInterface', $visitingMethod)) {
|
||||
if (!method_exists(__NAMESPACE__.'\RoleVisitorInterface', $visitingMethod)) {
|
||||
throw new \InvalidArgumentException("The visitor you provide cannot visit a $klass instance");
|
||||
}
|
||||
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Behavioral\Visitor;
|
||||
|
||||
/**
|
||||
* Visitor Pattern
|
||||
* Visitor Pattern.
|
||||
*
|
||||
* An implementation of a concrete Visitor
|
||||
*/
|
||||
@@ -14,7 +14,7 @@ class RolePrintVisitor implements RoleVisitorInterface
|
||||
*/
|
||||
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)
|
||||
{
|
||||
echo "Role: " . $role->getName();
|
||||
echo 'Role: '.$role->getName();
|
||||
}
|
||||
}
|
||||
|
@@ -3,11 +3,11 @@
|
||||
namespace DesignPatterns\Behavioral\Visitor;
|
||||
|
||||
/**
|
||||
* Visitor Pattern
|
||||
* Visitor Pattern.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Note 2 : the visitor must not choose itself which method to
|
||||
@@ -16,14 +16,14 @@ namespace DesignPatterns\Behavioral\Visitor;
|
||||
interface RoleVisitorInterface
|
||||
{
|
||||
/**
|
||||
* Visit a User object
|
||||
* Visit a User object.
|
||||
*
|
||||
* @param \DesignPatterns\Behavioral\Visitor\User $role
|
||||
*/
|
||||
public function visitUser(User $role);
|
||||
|
||||
/**
|
||||
* Visit a Group object
|
||||
* Visit a Group object.
|
||||
*
|
||||
* @param \DesignPatterns\Behavioral\Visitor\Group $role
|
||||
*/
|
||||
|
@@ -5,11 +5,10 @@ namespace DesignPatterns\Tests\Visitor\Tests;
|
||||
use DesignPatterns\Behavioral\Visitor;
|
||||
|
||||
/**
|
||||
* VisitorTest tests the visitor pattern
|
||||
* VisitorTest tests the visitor pattern.
|
||||
*/
|
||||
class VisitorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
protected $visitor;
|
||||
|
||||
protected function setUp()
|
||||
@@ -20,8 +19,8 @@ class VisitorTest extends \PHPUnit_Framework_TestCase
|
||||
public function getRole()
|
||||
{
|
||||
return array(
|
||||
array(new Visitor\User("Dominik"), 'Role: User Dominik'),
|
||||
array(new Visitor\Group("Administrators"), 'Role: Group: Administrators')
|
||||
array(new Visitor\User('Dominik'), 'Role: User Dominik'),
|
||||
array(new Visitor\Group('Administrators'), 'Role: Group: Administrators'),
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Behavioral\Visitor;
|
||||
|
||||
/**
|
||||
* Visitor Pattern
|
||||
* Visitor Pattern.
|
||||
*
|
||||
* One example for a visitee. Each visitee has to extends Role
|
||||
*/
|
||||
@@ -27,6 +27,6 @@ class User extends Role
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return "User " . $this->name;
|
||||
return 'User '.$this->name;
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Creational\AbstractFactory;
|
||||
|
||||
/**
|
||||
* class AbstractFactory
|
||||
* class AbstractFactory.
|
||||
*
|
||||
* Sometimes also known as "Kit" in a GUI libraries.
|
||||
*
|
||||
@@ -20,7 +20,7 @@ namespace DesignPatterns\Creational\AbstractFactory;
|
||||
abstract class AbstractFactory
|
||||
{
|
||||
/**
|
||||
* Creates a text component
|
||||
* Creates a text component.
|
||||
*
|
||||
* @param string $content
|
||||
*
|
||||
@@ -29,7 +29,7 @@ abstract class AbstractFactory
|
||||
abstract public function createText($content);
|
||||
|
||||
/**
|
||||
* Creates a picture component
|
||||
* Creates a picture component.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $name
|
||||
|
@@ -5,14 +5,14 @@ namespace DesignPatterns\Creational\AbstractFactory\Html;
|
||||
use DesignPatterns\Creational\AbstractFactory\Picture as BasePicture;
|
||||
|
||||
/**
|
||||
* Class Picture
|
||||
* Class Picture.
|
||||
*
|
||||
* Picture is a concrete image for HTML rendering
|
||||
*/
|
||||
class Picture extends BasePicture
|
||||
{
|
||||
/**
|
||||
* some crude rendering from HTML output
|
||||
* some crude rendering from HTML output.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@@ -5,19 +5,19 @@ namespace DesignPatterns\Creational\AbstractFactory\Html;
|
||||
use DesignPatterns\Creational\AbstractFactory\Text as BaseText;
|
||||
|
||||
/**
|
||||
* Class Text
|
||||
* Class Text.
|
||||
*
|
||||
* Text is a concrete text for HTML rendering
|
||||
*/
|
||||
class Text extends BaseText
|
||||
{
|
||||
/**
|
||||
* some crude rendering from HTML output
|
||||
* some crude rendering from HTML output.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return '<div>' . htmlspecialchars($this->text) . '</div>';
|
||||
return '<div>'.htmlspecialchars($this->text).'</div>';
|
||||
}
|
||||
}
|
||||
|
@@ -3,14 +3,14 @@
|
||||
namespace DesignPatterns\Creational\AbstractFactory;
|
||||
|
||||
/**
|
||||
* Class HtmlFactory
|
||||
* Class HtmlFactory.
|
||||
*
|
||||
* HtmlFactory is a concrete factory for HTML component
|
||||
*/
|
||||
class HtmlFactory extends AbstractFactory
|
||||
{
|
||||
/**
|
||||
* Creates a picture component
|
||||
* Creates a picture component.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $name
|
||||
@@ -23,7 +23,7 @@ class HtmlFactory extends AbstractFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a text component
|
||||
* Creates a text component.
|
||||
*
|
||||
* @param string $content
|
||||
*
|
||||
|
@@ -5,14 +5,14 @@ namespace DesignPatterns\Creational\AbstractFactory\Json;
|
||||
use DesignPatterns\Creational\AbstractFactory\Picture as BasePicture;
|
||||
|
||||
/**
|
||||
* Class Picture
|
||||
* Class Picture.
|
||||
*
|
||||
* Picture is a concrete image for JSON rendering
|
||||
*/
|
||||
class Picture extends BasePicture
|
||||
{
|
||||
/**
|
||||
* some crude rendering from JSON output
|
||||
* some crude rendering from JSON output.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@@ -5,14 +5,14 @@ namespace DesignPatterns\Creational\AbstractFactory\Json;
|
||||
use DesignPatterns\Creational\AbstractFactory\Text as BaseText;
|
||||
|
||||
/**
|
||||
* Class Text
|
||||
* Class Text.
|
||||
*
|
||||
* Text is a text component with a JSON rendering
|
||||
*/
|
||||
class Text extends BaseText
|
||||
{
|
||||
/**
|
||||
* some crude rendering from JSON output
|
||||
* some crude rendering from JSON output.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@@ -3,16 +3,15 @@
|
||||
namespace DesignPatterns\Creational\AbstractFactory;
|
||||
|
||||
/**
|
||||
* Class JsonFactory
|
||||
* Class JsonFactory.
|
||||
*
|
||||
* JsonFactory is a factory for creating a family of JSON component
|
||||
* (example for ajax)
|
||||
*/
|
||||
class JsonFactory extends AbstractFactory
|
||||
{
|
||||
|
||||
/**
|
||||
* Creates a picture component
|
||||
* Creates a picture component.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $name
|
||||
@@ -25,7 +24,7 @@ class JsonFactory extends AbstractFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a text component
|
||||
* Creates a text component.
|
||||
*
|
||||
* @param string $content
|
||||
*
|
||||
|
@@ -3,16 +3,15 @@
|
||||
namespace DesignPatterns\Creational\AbstractFactory;
|
||||
|
||||
/**
|
||||
* Interface MediaInterface
|
||||
* Interface MediaInterface.
|
||||
*
|
||||
* This contract is not part of the pattern, in general case, each component
|
||||
* are not related
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
@@ -3,11 +3,10 @@
|
||||
namespace DesignPatterns\Creational\AbstractFactory;
|
||||
|
||||
/**
|
||||
* Class Picture
|
||||
* Class Picture.
|
||||
*/
|
||||
abstract class Picture implements MediaInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
|
@@ -7,7 +7,7 @@ use DesignPatterns\Creational\AbstractFactory\HtmlFactory;
|
||||
use DesignPatterns\Creational\AbstractFactory\JsonFactory;
|
||||
|
||||
/**
|
||||
* AbstractFactoryTest tests concrete factories
|
||||
* AbstractFactoryTest tests concrete factories.
|
||||
*/
|
||||
class AbstractFactoryTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
@@ -15,7 +15,7 @@ class AbstractFactoryTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
return array(
|
||||
array(new JsonFactory()),
|
||||
array(new HtmlFactory())
|
||||
array(new HtmlFactory()),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ class AbstractFactoryTest extends \PHPUnit_Framework_TestCase
|
||||
$article = array(
|
||||
$factory->createText('Lorem Ipsum'),
|
||||
$factory->createPicture('/image.jpg', 'caption'),
|
||||
$factory->createText('footnotes')
|
||||
$factory->createText('footnotes'),
|
||||
);
|
||||
|
||||
$this->assertContainsOnly('DesignPatterns\Creational\AbstractFactory\MediaInterface', $article);
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Creational\AbstractFactory;
|
||||
|
||||
/**
|
||||
* Class Text
|
||||
* Class Text.
|
||||
*/
|
||||
abstract class Text implements MediaInterface
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Creational\Builder;
|
||||
|
||||
/**
|
||||
* BikeBuilder builds bike
|
||||
* BikeBuilder builds bike.
|
||||
*/
|
||||
class BikeBuilder implements BuilderInterface
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Creational\Builder;
|
||||
|
||||
/**
|
||||
* CarBuilder builds car
|
||||
* CarBuilder builds car.
|
||||
*/
|
||||
class CarBuilder implements BuilderInterface
|
||||
{
|
||||
|
@@ -10,9 +10,8 @@ namespace DesignPatterns\Creational\Builder;
|
||||
*/
|
||||
class Director
|
||||
{
|
||||
|
||||
/**
|
||||
* The director don't know 'bout concrete part
|
||||
* The director don't know about concrete part.
|
||||
*
|
||||
* @param BuilderInterface $builder
|
||||
*
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Creational\Builder\Parts;
|
||||
|
||||
/**
|
||||
* Bike is a bike
|
||||
* Bike is a bike.
|
||||
*/
|
||||
class Bike extends Vehicle
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Creational\Builder\Parts;
|
||||
|
||||
/**
|
||||
* Car is a car
|
||||
* Car is a car.
|
||||
*/
|
||||
class Car extends Vehicle
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Creational\Builder\Parts;
|
||||
|
||||
/**
|
||||
* Class Door
|
||||
* Class Door.
|
||||
*/
|
||||
class Door
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Creational\Builder\Parts;
|
||||
|
||||
/**
|
||||
* Class Engine
|
||||
* Class Engine.
|
||||
*/
|
||||
class Engine
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Creational\Builder\Parts;
|
||||
|
||||
/**
|
||||
* VehicleInterface is a contract for a vehicle
|
||||
* Vehicle class is an abstraction for a vehicle.
|
||||
*/
|
||||
abstract class Vehicle
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Creational\Builder\Parts;
|
||||
|
||||
/**
|
||||
* Class Wheel
|
||||
* Class Wheel.
|
||||
*/
|
||||
class Wheel
|
||||
{
|
||||
|
@@ -2,17 +2,16 @@
|
||||
|
||||
namespace DesignPatterns\Creational\Builder\Tests;
|
||||
|
||||
use DesignPatterns\Creational\Builder\Director;
|
||||
use DesignPatterns\Creational\Builder\CarBuilder;
|
||||
use DesignPatterns\Creational\Builder\BikeBuilder;
|
||||
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
|
||||
{
|
||||
|
||||
protected $director;
|
||||
|
||||
protected function setUp()
|
||||
@@ -24,7 +23,7 @@ class DirectorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
return array(
|
||||
array(new CarBuilder()),
|
||||
array(new BikeBuilder())
|
||||
array(new BikeBuilder()),
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Creational\FactoryMethod;
|
||||
|
||||
/**
|
||||
* Bicycle is a bicycle
|
||||
* Bicycle is a bicycle.
|
||||
*/
|
||||
class Bicycle implements VehicleInterface
|
||||
{
|
||||
@@ -13,7 +13,7 @@ class Bicycle implements VehicleInterface
|
||||
protected $color;
|
||||
|
||||
/**
|
||||
* sets the color of the bicycle
|
||||
* sets the color of the bicycle.
|
||||
*
|
||||
* @param string $rgb
|
||||
*/
|
||||
|
@@ -3,16 +3,15 @@
|
||||
namespace DesignPatterns\Creational\FactoryMethod;
|
||||
|
||||
/**
|
||||
* class FactoryMethod
|
||||
* class FactoryMethod.
|
||||
*/
|
||||
abstract class FactoryMethod
|
||||
{
|
||||
|
||||
const CHEAP = 1;
|
||||
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
|
||||
*
|
||||
@@ -23,7 +22,7 @@ abstract class FactoryMethod
|
||||
abstract protected function createVehicle($type);
|
||||
|
||||
/**
|
||||
* Creates a new vehicle
|
||||
* Creates a new vehicle.
|
||||
*
|
||||
* @param int $type
|
||||
*
|
||||
@@ -32,7 +31,7 @@ abstract class FactoryMethod
|
||||
public function create($type)
|
||||
{
|
||||
$obj = $this->createVehicle($type);
|
||||
$obj->setColor("#f00");
|
||||
$obj->setColor('#f00');
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Creational\FactoryMethod;
|
||||
|
||||
/**
|
||||
* Ferrari is a italian car
|
||||
* Ferrari is a italian car.
|
||||
*/
|
||||
class Ferrari implements VehicleInterface
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Creational\FactoryMethod;
|
||||
|
||||
/**
|
||||
* GermanFactory is a vehicle factory in Germany
|
||||
* GermanFactory is a vehicle factory in Germany.
|
||||
*/
|
||||
class GermanFactory extends FactoryMethod
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Creational\FactoryMethod;
|
||||
|
||||
/**
|
||||
* ItalianFactory is vehicle factory in Italy
|
||||
* ItalianFactory is vehicle factory in Italy.
|
||||
*/
|
||||
class ItalianFactory extends FactoryMethod
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Creational\FactoryMethod;
|
||||
|
||||
/**
|
||||
* Porsche is a german car
|
||||
* Porsche is a german car.
|
||||
*/
|
||||
class Porsche implements VehicleInterface
|
||||
{
|
||||
|
@@ -7,21 +7,20 @@ use DesignPatterns\Creational\FactoryMethod\GermanFactory;
|
||||
use DesignPatterns\Creational\FactoryMethod\ItalianFactory;
|
||||
|
||||
/**
|
||||
* FactoryMethodTest tests the factory method pattern
|
||||
* FactoryMethodTest tests the factory method pattern.
|
||||
*/
|
||||
class FactoryMethodTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
protected $type = array(
|
||||
FactoryMethod::CHEAP,
|
||||
FactoryMethod::FAST
|
||||
FactoryMethod::FAST,
|
||||
);
|
||||
|
||||
public function getShop()
|
||||
{
|
||||
return array(
|
||||
array(new GermanFactory()),
|
||||
array(new ItalianFactory())
|
||||
array(new ItalianFactory()),
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -3,12 +3,12 @@
|
||||
namespace DesignPatterns\Creational\FactoryMethod;
|
||||
|
||||
/**
|
||||
* VehicleInterface is a contract for a vehicle
|
||||
* VehicleInterface is a contract for a vehicle.
|
||||
*/
|
||||
interface VehicleInterface
|
||||
{
|
||||
/**
|
||||
* sets the color of the vehicle
|
||||
* sets the color of the vehicle.
|
||||
*
|
||||
* @param string $rgb
|
||||
*/
|
||||
|
@@ -3,24 +3,22 @@
|
||||
namespace DesignPatterns\Creational\Multiton;
|
||||
|
||||
/**
|
||||
* class Multiton
|
||||
* class Multiton.
|
||||
*/
|
||||
class Multiton
|
||||
{
|
||||
/**
|
||||
*
|
||||
* the first instance
|
||||
* the first instance.
|
||||
*/
|
||||
const INSTANCE_1 = '1';
|
||||
|
||||
/**
|
||||
*
|
||||
* the second instance
|
||||
* the second instance.
|
||||
*/
|
||||
const INSTANCE_2 = '2';
|
||||
|
||||
/**
|
||||
* holds the named instances
|
||||
* holds the named instances.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
@@ -28,7 +26,6 @@ class Multiton
|
||||
|
||||
/**
|
||||
* should not be called from outside: private!
|
||||
*
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
@@ -36,7 +33,7 @@ class Multiton
|
||||
|
||||
/**
|
||||
* gets the instance with the given name, e.g. Multiton::INSTANCE_1
|
||||
* uses lazy initialization
|
||||
* uses lazy initialization.
|
||||
*
|
||||
* @param string $instanceName
|
||||
*
|
||||
@@ -52,7 +49,7 @@ class Multiton
|
||||
}
|
||||
|
||||
/**
|
||||
* prevent instance from being cloned
|
||||
* prevent instance from being cloned.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
@@ -61,7 +58,7 @@ class Multiton
|
||||
}
|
||||
|
||||
/**
|
||||
* prevent instance from being unserialized
|
||||
* prevent instance from being unserialized.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
@@ -4,7 +4,6 @@ namespace DesignPatterns\Creational\Pool;
|
||||
|
||||
class Pool
|
||||
{
|
||||
|
||||
private $instances = array();
|
||||
private $class;
|
||||
|
||||
|
@@ -4,11 +4,10 @@ namespace DesignPatterns\Creational\Pool;
|
||||
|
||||
class Processor
|
||||
{
|
||||
|
||||
private $pool;
|
||||
private $processing = 0;
|
||||
private $maxProcesses = 3;
|
||||
private $waitingQueue = [];
|
||||
private $waitingQueue = array();
|
||||
|
||||
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