Merge branch 'master' into flyweight

This commit is contained in:
Dominik Liebler
2016-04-07 08:37:35 +02:00
475 changed files with 21899 additions and 1317 deletions

5
.gitignore vendored
View File

@@ -2,3 +2,8 @@
.idea
/nbproject
/vendor/
_build/
*.mo
.vagrant/
phpunit.xml
composer.phar

View File

@@ -1,19 +1,31 @@
language: php
sudo: false
php:
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
before_script:
- composer self-update
- composer install --prefer-source --no-interaction --dev
branches:
only:
- master
matrix:
allow_failures:
- php: hhvm
- php: 7.0
fast_finish: true
cache:
directories:
- $HOME/.composer/cache
before_install:
- composer self-update
- composer validate
install:
- composer install --prefer-dist --no-interaction
script:
- vendor/bin/phpunit

View File

@@ -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
*

View File

@@ -1,16 +0,0 @@
# Chain Of Responsibilities
## Purpose:
To build a chain of objects to handle a call in sequential order. If one object cannot handle a call, it delegates the call to the next in the chain and so forth.
## Examples:
* logging framework, where each chain element decides autonomously what to do with a log message
* a Spam filter
* Caching: first object is an instance of e.g. a Memcached Interface, if that "misses" it delegates the call to the database interface
* Yii Framework: CFilterChain is a chain of controller action filters. the executing point is passed from one filter to the next along the chain, and only if all filters say "yes", the action can be invoked at last.
## UML Diagram
![Alt ChainOfResponsibility UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,70 @@
`Chain Of Responsibilities`__
=============================
Purpose:
--------
To build a chain of objects to handle a call in sequential order. If one
object cannot handle a call, it delegates the call to the next in the
chain and so forth.
Examples:
---------
- logging framework, where each chain element decides autonomously what
to do with a log message
- a Spam filter
- Caching: first object is an instance of e.g. a Memcached Interface,
if that "misses" it delegates the call to the database interface
- Yii Framework: CFilterChain is a chain of controller action filters.
the executing point is passed from one filter to the next along the
chain, and only if all filters say "yes", the action can be invoked
at last.
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt ChainOfResponsibility UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
Request.php
.. literalinclude:: Request.php
:language: php
:linenos:
Handler.php
.. literalinclude:: Handler.php
:language: php
:linenos:
Responsible/SlowStorage.php
.. literalinclude:: Responsible/SlowStorage.php
:language: php
:linenos:
Responsible/FastStorage.php
.. literalinclude:: Responsible/FastStorage.php
:language: php
:linenos:
Test
----
Tests/ChainTest.php
.. literalinclude:: Tests/ChainTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Behavioral/ChainOfResponsibilities
.. __: http://en.wikipedia.org/wiki/Chain_of_responsibility_pattern

View File

@@ -6,7 +6,7 @@ use DesignPatterns\Behavioral\ChainOfResponsibilities\Handler;
use DesignPatterns\Behavioral\ChainOfResponsibilities\Request;
/**
* Class FastStorage
* Class FastStorage.
*/
class FastStorage extends Handler
{

View File

@@ -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
{

View File

@@ -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),
);
}

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

View File

@@ -3,7 +3,7 @@
namespace DesignPatterns\Behavioral\Command;
/**
* class CommandInterface
* class CommandInterface.
*/
interface CommandInterface
{

View File

@@ -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()
{

View File

@@ -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()
{

View File

@@ -1,21 +0,0 @@
# Command
## Purpose
To encapsulate invocation and decoupling.
We have an Invoker and a Receiver. This pattern uses a "Command" to delegate the method call against the Receiver and presents the same method "execute".
Therefore, the Invoker just knows to call "execute" to process the Command of the client. The Receiver is decoupled from the Invoker.
The second aspect of this pattern is the undo(), which undoes the method execute().
Command can also be aggregated to combine more complex commands with minimum copy-paste and relying on composition over inheritance.
## Examples
* A text editor : all events are Command which can be undone, stacked and saved.
* Symfony2: SF2 Commands that can be run from the CLI are built with just the Command pattern in mind
* big CLI tools use subcommands to distribute various tasks and pack them in "modules", each of these can be implemented with the Command pattern (e.g. vagrant)
## UML Diagram
![Alt Command UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,77 @@
`Command`__
===========
Purpose
-------
To encapsulate invocation and decoupling.
We have an Invoker and a Receiver. This pattern uses a "Command" to
delegate the method call against the Receiver and presents the same
method "execute". Therefore, the Invoker just knows to call "execute" to
process the Command of the client. The Receiver is decoupled from the
Invoker.
The second aspect of this pattern is the undo(), which undoes the method
execute(). Command can also be aggregated to combine more complex
commands with minimum copy-paste and relying on composition over
inheritance.
Examples
--------
- A text editor : all events are Command which can be undone, stacked
and saved.
- Symfony2: SF2 Commands that can be run from the CLI are built with
just the Command pattern in mind
- big CLI tools use subcommands to distribute various tasks and pack
them in "modules", each of these can be implemented with the Command
pattern (e.g. vagrant)
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Command UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
CommandInterface.php
.. literalinclude:: CommandInterface.php
:language: php
:linenos:
HelloCommand.php
.. literalinclude:: HelloCommand.php
:language: php
:linenos:
Receiver.php
.. literalinclude:: Receiver.php
:language: php
:linenos:
Invoker.php
.. literalinclude:: Invoker.php
:language: php
:linenos:
Test
----
Tests/CommandTest.php
.. literalinclude:: Tests/CommandTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Behavioral/Command
.. __: http://en.wikipedia.org/wiki/Command_pattern

View File

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

View File

@@ -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');
}
}

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

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

View File

@@ -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();
}
}

View File

@@ -4,35 +4,30 @@ 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)
{
foreach ($this as $key => $book) {
foreach ($this->books as $key => $book) {
/** @var Book $book */
if ($book->getAuthorAndTitle() === $bookToRemove->getAuthorAndTitle()) {
unset($this->books[$key]);
}
}
return $this->count();
}
public function count()

View File

@@ -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 &gt;= 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 &gt;= 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 &gt;= 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 &gt;= 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()

View File

@@ -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 &gt;= 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 &gt;= 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 &gt;= 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 &gt;= 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;
}
}

View File

@@ -1,17 +0,0 @@
# Iterator
## Purpose
To make an object iterable and to make it appear like a collection of objects.
## Examples
* to process a file line by line by just running over all lines (which have an object representation) for a file (which of course is an object, too)
## Note
Standard PHP Library (SPL) defines an interface Iterator which is best suited for this! Often you would want to implement the Countable interface too, to allow `count($object)` on your iterable object
## UML Diagram
![Alt Iterator UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,70 @@
`Iterator`__
============
Purpose
-------
To make an object iterable and to make it appear like a collection of
objects.
Examples
--------
- to process a file line by line by just running over all lines (which
have an object representation) for a file (which of course is an
object, too)
Note
----
Standard PHP Library (SPL) defines an interface Iterator which is best
suited for this! Often you would want to implement the Countable
interface too, to allow ``count($object)`` on your iterable object
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Iterator UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
Book.php
.. literalinclude:: Book.php
:language: php
:linenos:
BookList.php
.. literalinclude:: BookList.php
:language: php
:linenos:
BookListIterator.php
.. literalinclude:: BookListIterator.php
:language: php
:linenos:
BookListReverseIterator.php
.. literalinclude:: BookListReverseIterator.php
:language: php
:linenos:
Test
----
Tests/IteratorTest.php
.. literalinclude:: Tests/IteratorTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Behavioral/Iterator
.. __: http://en.wikipedia.org/wiki/Iterator_pattern

View File

@@ -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',
),
),
);
}
@@ -63,4 +62,13 @@ class IteratorTest extends \PHPUnit_Framework_TestCase
$iterator->next();
}
}
/**
* Test BookList Remove.
*/
public function testBookRemove()
{
$this->bookList->removeBook($this->bookList->getBook(0));
$this->assertEquals($this->bookList->count(), 2);
}
}

View File

@@ -9,18 +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;
// for subclasses
protected function getMediator()
{
return $this->mediator;
}
/**
* @param MediatorInterface $medium
*/
@@ -29,4 +23,11 @@ abstract class Colleague
// in this way, we are sure the concrete colleague knows the mediator
$this->mediator = $medium;
}
// for subclasses
protected function getMediator()
{
return $this->mediator;
}
}

View File

@@ -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
*/

View File

@@ -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();
}

View File

@@ -1,15 +0,0 @@
# Mediator
## Purpose
This pattern provides an easy to decouple many components working together.
It is a good alternative over 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 MediatorInterface and
it is a good thing because in OOP, one good friend is better than many. This
is the key-feature of this pattern.
## UML Diagram
![Alt Mediator UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,73 @@
`Mediator`__
============
Purpose
-------
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
MediatorInterface and it is a good thing because in OOP, one good friend
is better than many. This is the key-feature of this pattern.
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Mediator UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
MediatorInterface.php
.. literalinclude:: MediatorInterface.php
:language: php
:linenos:
Mediator.php
.. literalinclude:: Mediator.php
:language: php
:linenos:
Colleague.php
.. literalinclude:: Colleague.php
:language: php
:linenos:
Subsystem/Client.php
.. literalinclude:: Subsystem/Client.php
:language: php
:linenos:
Subsystem/Database.php
.. literalinclude:: Subsystem/Database.php
:language: php
:linenos:
Subsystem/Server.php
.. literalinclude:: Subsystem/Server.php
:language: php
:linenos:
Test
----
Tests/MediatorTest.php
.. literalinclude:: Tests/MediatorTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Behavioral/Mediator
.. __: http://en.wikipedia.org/wiki/Mediator_pattern

View File

@@ -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
*/

View File

@@ -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';
}
}

View File

@@ -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()
{

View File

@@ -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()

View File

@@ -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();
}
}

View File

@@ -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);

View File

@@ -1,22 +0,0 @@
# Memento
## Purpose
Provide the ability to restore an object to its previous state (undo via rollback).
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.
## Examples
* The seed of a pseudorandom number generator
* The state in a finite state machine
## UML Diagram
![Alt Momento UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,85 @@
`Memento`__
===========
Purpose
-------
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.
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
-----------
.. image:: uml/uml.png
:alt: Alt Momento UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
Memento.php
.. literalinclude:: Memento.php
:language: php
:linenos:
Originator.php
.. literalinclude:: Originator.php
:language: php
:linenos:
Caretaker.php
.. literalinclude:: Caretaker.php
:language: php
:linenos:
Test
----
Tests/MementoTest.php
.. literalinclude:: Tests/MementoTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Behavioral/Memento
.. __: http://en.wikipedia.org/wiki/Memento_pattern

View File

@@ -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

View File

@@ -3,8 +3,8 @@
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
*/
interface LoggerInterface

View File

@@ -5,7 +5,7 @@ namespace DesignPatterns\Behavioral\NullObject;
/**
* Performance concerns : ok there is a call for nothing but we spare an "if is_null"
* I didn't run a benchmark but I think it's equivalent.
*
*
* Key feature : of course this logger MUST implement the same interface (or abstract)
* like the other loggers.
*/

View File

@@ -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
{

View File

@@ -1,22 +0,0 @@
# Null Object
## Purpose
NullObject is not a GoF design pattern but a schema which appears frequently enough to be considered a pattern. It has the following benefits:
* Client code is simplified
* Reduces the chance of null pointer exceptions
* Fewer conditionals require less test cases
Methods that return an object or null should instead return an object or `NullObject`. `NullObject`s simplify boilerplate code such as `if (!is_null($obj)) { $obj->callSomething(); }` to just `$obj->callSomething();` by eliminating the conditional check in client code.
## Examples
* Symfony2: null logger of profiler
* Symfony2: null output in Symfony/Console
* null handler in a Chain of Responsibilities pattern
* null command in a Command pattern
## UML Diagram
![Alt NullObject UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,75 @@
`Null Object`__
===============
Purpose
-------
NullObject is not a GoF design pattern but a schema which appears
frequently enough to be considered a pattern. It has the following
benefits:
- Client code is simplified
- Reduces the chance of null pointer exceptions
- Fewer conditionals require less test cases
Methods that return an object or null should instead return an object or
``NullObject``. ``NullObject``\ s simplify boilerplate code such as
``if (!is_null($obj)) { $obj->callSomething(); }`` to just
``$obj->callSomething();`` by eliminating the conditional check in
client code.
Examples
--------
- Symfony2: null logger of profiler
- Symfony2: null output in Symfony/Console
- null handler in a Chain of Responsibilities pattern
- null command in a Command pattern
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt NullObject UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
Service.php
.. literalinclude:: Service.php
:language: php
:linenos:
LoggerInterface.php
.. literalinclude:: LoggerInterface.php
:language: php
:linenos:
PrintLogger.php
.. literalinclude:: PrintLogger.php
:language: php
:linenos:
NullLogger.php
.. literalinclude:: NullLogger.php
:language: php
:linenos:
Test
----
Tests/LoggerTest.php
.. literalinclude:: Tests/LoggerTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Behavioral/NullObject
.. __: http://en.wikipedia.org/wiki/Null_Object_pattern

View File

@@ -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...
}
}

View File

@@ -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

View File

@@ -1,18 +0,0 @@
# Observer
## Purpose
To implement a publish/subscribe behaviour to an object, whenever a "Subject" object changes it's state, the attached
"Observers" will be notified. It is used to shorten the amount of coupled objects and uses loose coupling instead.
## Examples
* a message queue system is observed to show the progress of a job in a GUI
## Note
PHP already defines two interfaces that can help to implement this pattern: SplObserver and SplSubject.
## UML Diagram
![Alt Observer UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,58 @@
`Observer`__
============
Purpose
-------
To implement a publish/subscribe behaviour to an object, whenever a
"Subject" object changes it's state, the attached "Observers" will be
notified. It is used to shorten the amount of coupled objects and uses
loose coupling instead.
Examples
--------
- a message queue system is observed to show the progress of a job in a
GUI
Note
----
PHP already defines two interfaces that can help to implement this
pattern: SplObserver and SplSubject.
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Observer UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
User.php
.. literalinclude:: User.php
:language: php
:linenos:
UserObserver.php
.. literalinclude:: UserObserver.php
:language: php
:linenos:
Test
----
Tests/ObserverTest.php
.. literalinclude:: Tests/ObserverTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Behavioral/Observer
.. __: http://en.wikipedia.org/wiki/Observer_pattern

View File

@@ -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,20 +30,29 @@ class ObserverTest extends \PHPUnit_Framework_TestCase
}
/**
* Tests the subscribing
* Tests the subscribing.
*/
public function testAttachDetach()
{
$subject = new User();
$this->assertAttributeEmpty('observers', $subject);
$reflection = new \ReflectionProperty($subject, 'observers');
$reflection->setAccessible(true);
/** @var \SplObjectStorage $observers */
$observers = $reflection->getValue($subject);
$this->assertInstanceOf('SplObjectStorage', $observers);
$this->assertFalse($observers->contains($this->observer));
$subject->attach($this->observer);
$this->assertAttributeNotEmpty('observers', $subject);
$this->assertTrue($observers->contains($this->observer));
$subject->detach($this->observer);
$this->assertAttributeEmpty('observers', $subject);
$this->assertFalse($observers->contains($this->observer));
}
/**
* Tests the update() invocation on a mockup
* Tests the update() invocation on a mockup.
*/
public function testUpdateCalling()
{

View File

@@ -3,29 +3,33 @@
namespace DesignPatterns\Behavioral\Observer;
/**
* Observer pattern : The observed object (the subject)
*
* The subject maintains a list of Observers and sends notifications.
* 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 array
* @var \SplObjectStorage
*/
protected $observers = array();
protected $observers;
public function __construct()
{
$this->observers = new \SplObjectStorage();
}
/**
* attach a new observer
* attach a new observer.
*
* @param \SplObserver $observer
*
@@ -33,11 +37,11 @@ class User implements \SplSubject
*/
public function attach(\SplObserver $observer)
{
$this->observers[] = $observer;
$this->observers->attach($observer);
}
/**
* detach an observer
* detach an observer.
*
* @param \SplObserver $observer
*
@@ -45,15 +49,11 @@ class User implements \SplSubject
*/
public function detach(\SplObserver $observer)
{
$index = array_search($observer, $this->observers);
if (false !== $index) {
unset($this->observers[$index]);
}
$this->observers->detach($observer);
}
/**
* notify observers
* notify observers.
*
* @return void
*/
@@ -67,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

View File

@@ -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';
}
}

View File

@@ -9,6 +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](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)

25
Behavioral/README.rst Normal file
View File

@@ -0,0 +1,25 @@
`Behavioral`__
==============
In software engineering, behavioral design patterns are design patterns
that identify common communication patterns between objects and realize
these patterns. By doing so, these patterns increase flexibility in
carrying out this communication.
.. toctree::
:titlesonly:
ChainOfResponsibilities/README
Command/README
Iterator/README
Mediator/README
Memento/README
NullObject/README
Observer/README
Specification/README
State/README
Strategy/README
TemplateMethod/README
Visitor/README
.. __: http://en.wikipedia.org/wiki/Behavioral_pattern

View File

@@ -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
*/

View File

@@ -1,18 +1,18 @@
<?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,10 +23,10 @@ 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
*
*
* @return bool
*/
public function isSatisfiedBy(Item $item)

View File

@@ -1,16 +1,17 @@
<?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
*/
public function __construct($price)
@@ -19,8 +20,8 @@ class Item
}
/**
* Get the items price
*
* Get the items price.
*
* @return int
*/
public function getPrice()

View File

@@ -1,17 +1,17 @@
<?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
*/
public function __construct(SpecificationInterface $spec)
@@ -20,10 +20,10 @@ class Not extends AbstractSpecification
}
/**
* Returns the negated result of the wrapped specification
*
* Returns the negated result of the wrapped specification.
*
* @param Item $item
*
*
* @return bool
*/
public function isSatisfiedBy(Item $item)

View File

@@ -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 locical 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
*

View File

@@ -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
*

View File

@@ -1,10 +0,0 @@
# Specification
## Purpose
Builds a clear specification of business rules, where objects can be checked against. The composite specification class has
one method called `isSatisfiedBy` that returns either true or false depending on whether the given object satisfies the specification.
## UML Diagram
![Alt Specification UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,81 @@
`Specification`__
=================
Purpose
-------
Builds a clear specification of business rules, where objects can be
checked against. The composite specification class has one method called
``isSatisfiedBy`` that returns either true or false depending on whether
the given object satisfies the specification.
Examples
--------
- `RulerZ <https://github.com/K-Phoen/rulerz>`__
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Specification UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
Item.php
.. literalinclude:: Item.php
:language: php
:linenos:
SpecificationInterface.php
.. literalinclude:: SpecificationInterface.php
:language: php
:linenos:
AbstractSpecification.php
.. literalinclude:: AbstractSpecification.php
:language: php
:linenos:
Either.php
.. literalinclude:: Either.php
:language: php
:linenos:
PriceSpecification.php
.. literalinclude:: PriceSpecification.php
:language: php
:linenos:
Plus.php
.. literalinclude:: Plus.php
:language: php
:linenos:
Not.php
.. literalinclude:: Not.php
:language: php
:linenos:
Test
----
Tests/SpecificationTest.php
.. literalinclude:: Tests/SpecificationTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Behavioral/Specification
.. __: http://en.wikipedia.org/wiki/Specification_pattern

View File

@@ -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();
}

View File

@@ -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
{

View File

@@ -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()
{

View File

@@ -3,7 +3,7 @@
namespace DesignPatterns\Behavioral\State;
/**
* Class OrderController
* Class OrderController.
*/
class OrderController
{

View File

@@ -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)
{

View File

@@ -3,7 +3,7 @@
namespace DesignPatterns\Behavioral\State;
/**
* Class OrderInterface
* Class OrderInterface.
*/
interface OrderInterface
{

View File

@@ -1,9 +0,0 @@
# State
## Purpose
Encapsulate varying behavior for the same routine based on an object's state. This can be a cleaner way for an object to change its behavior at runtime without resorting to large monolithic conditional statements.
## UML Diagram
![Alt State UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,57 @@
`State`__
=========
Purpose
-------
Encapsulate varying behavior for the same routine based on an object's
state. This can be a cleaner way for an object to change its behavior at
runtime without resorting to large monolithic conditional statements.
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt State UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
OrderController.php
.. literalinclude:: OrderController.php
:language: php
:linenos:
OrderFactory.php
.. literalinclude:: OrderFactory.php
:language: php
:linenos:
OrderInterface.php
.. literalinclude:: OrderInterface.php
:language: php
:linenos:
ShippingOrder.php
.. literalinclude:: ShippingOrder.php
:language: php
:linenos:
CreateOrder.php
.. literalinclude:: CreateOrder.php
:language: php
:linenos:
Test
----
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Behavioral/State
.. __: http://en.wikipedia.org/wiki/State_pattern

View File

@@ -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()
{
@@ -44,6 +45,6 @@ class ShippingOrder implements OrderInterface
$this->order['updatedTime'] = time();
// Setting the new order status into database;
return $this->updateOrder($order);
return $this->updateOrder($this->order);
}
}

View File

@@ -3,7 +3,7 @@
namespace DesignPatterns\Behavioral\Strategy;
/**
* Class ComparatorInterface
* Class ComparatorInterface.
*/
interface ComparatorInterface
{

View File

@@ -3,7 +3,7 @@
namespace DesignPatterns\Behavioral\Strategy;
/**
* Class DateComparator
* Class DateComparator.
*/
class DateComparator implements ComparatorInterface
{

View File

@@ -3,7 +3,7 @@
namespace DesignPatterns\Behavioral\Strategy;
/**
* Class IdComparator
* Class IdComparator.
*/
class IdComparator implements ComparatorInterface
{

View File

@@ -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');

View File

@@ -1,20 +0,0 @@
# Strategy
## Terminology:
* Context
* Strategy
* Concrete Strategy
## Purpose
To separate strategies and to enable fast switching between them. Also this pattern is a good alternative to inheritance (instead of having an abstract class that is extended).
## Examples
* sorting a list of objects, one strategy by date, the other by id
* simplify unit testing: e.g. switching between file and in-memory storage
## UML Diagram
![Alt Strategy UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,71 @@
`Strategy`__
============
Terminology:
------------
- Context
- Strategy
- Concrete Strategy
Purpose
-------
To separate strategies and to enable fast switching between them. Also
this pattern is a good alternative to inheritance (instead of having an
abstract class that is extended).
Examples
--------
- sorting a list of objects, one strategy by date, the other by id
- simplify unit testing: e.g. switching between file and in-memory
storage
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Strategy UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
ObjectCollection.php
.. literalinclude:: ObjectCollection.php
:language: php
:linenos:
ComparatorInterface.php
.. literalinclude:: ComparatorInterface.php
:language: php
:linenos:
DateComparator.php
.. literalinclude:: DateComparator.php
:language: php
:linenos:
IdComparator.php
.. literalinclude:: IdComparator.php
:language: php
:linenos:
Test
----
Tests/StrategyTest.php
.. literalinclude:: Tests/StrategyTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Behavioral/Strategy
.. __: http://en.wikipedia.org/wiki/Strategy_pattern

View File

@@ -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'),
),
);
}

View File

@@ -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()
{

View File

@@ -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()
{

View File

@@ -10,7 +10,7 @@ abstract class Journey
/**
* This is the public service provided by this class and its subclasses.
* Notice it is final to "freeze" the global behavior of algorithm.
* If you want to override this contract, make an interface with only takeATrip()
* If you want to override this contract, make an interface with only takeATrip()
* and subclass it.
*/
final public function takeATrip()
@@ -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()
{

View File

@@ -1,18 +0,0 @@
# Template Method
## Purpose
Template Method is a behavioral design pattern.
Perhaps you have encountered it many times already. The idea is to let subclasses of this abstract template "finish" the behavior of an algorithm.
A.k.a the "Hollywood principle": "Don't call us, we call you." This class is not called by subclasses but the inverse.
How? With abstraction of course.
In other words, this is a skeleton of algorithm, well-suited for framework libraries. The user has just to implement one method and the superclass do the job.
It is an easy way to decouple concrete classes and reduce copy-paste, that's why you'll find it everywhere.
## UML Diagram
![Alt TemplateMethod UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,64 @@
`Template Method`__
===================
Purpose
-------
Template Method is a behavioral design pattern.
Perhaps you have encountered it many times already. The idea is to let
subclasses of this abstract template "finish" the behavior of an
algorithm.
A.k.a the "Hollywood principle": "Don't call us, we call you." This
class is not called by subclasses but the inverse. How? With abstraction
of course.
In other words, this is a skeleton of algorithm, well-suited for
framework libraries. The user has just to implement one method and the
superclass do the job.
It is an easy way to decouple concrete classes and reduce copy-paste,
that's why you'll find it everywhere.
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt TemplateMethod UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
Journey.php
.. literalinclude:: Journey.php
:language: php
:linenos:
BeachJourney.php
.. literalinclude:: BeachJourney.php
:language: php
:linenos:
CityJourney.php
.. literalinclude:: CityJourney.php
:language: php
:linenos:
Test
----
Tests/JourneyTest.php
.. literalinclude:: Tests/JourneyTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Behavioral/TemplateMethod
.. __: http://en.wikipedia.org/wiki/Template_method_pattern

View File

@@ -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()
{

View File

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

View File

@@ -1,12 +0,0 @@
# Visitor
## Purpose
The Visitor Pattern lets you outsource operations on objects to other objects. The main reason to do this is to keep a separation of concerns.
But classes have to define a contract to allow visitors (the `Role::accept` method in the example).
The contract is an abstract class but you can have also a clean interface. In that case, each Visitor has to choose itself which method to invoke on the visitor.
## UML Diagram
![Alt Visitor UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,68 @@
`Visitor`__
===========
Purpose
-------
The Visitor Pattern lets you outsource operations on objects to other
objects. The main reason to do this is to keep a separation of concerns.
But classes have to define a contract to allow visitors (the
``Role::accept`` method in the example).
The contract is an abstract class but you can have also a clean
interface. In that case, each Visitor has to choose itself which method
to invoke on the visitor.
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Visitor UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
RoleVisitorInterface.php
.. literalinclude:: RoleVisitorInterface.php
:language: php
:linenos:
RolePrintVisitor.php
.. literalinclude:: RolePrintVisitor.php
:language: php
:linenos:
Role.php
.. literalinclude:: Role.php
:language: php
:linenos:
User.php
.. literalinclude:: User.php
:language: php
:linenos:
Group.php
.. literalinclude:: Group.php
:language: php
:linenos:
Test
----
Tests/VisitorTest.php
.. literalinclude:: Tests/VisitorTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Behavioral/Visitor
.. __: http://en.wikipedia.org/wiki/Visitor_pattern

View File

@@ -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");
}

View File

@@ -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();
}
}

View File

@@ -3,28 +3,28 @@
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
* invoke, it is the Visitee that make this decision.
*/
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
*/
public function visitGroup(Group $role);

View File

@@ -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'),
);
}

View File

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

View File

@@ -3,7 +3,7 @@
namespace DesignPatterns\Creational\AbstractFactory;
/**
* class AbstractFactory
* class AbstractFactory.
*
* Sometimes also known as "Kit" in a GUI libraries.
*
@@ -11,17 +11,17 @@ namespace DesignPatterns\Creational\AbstractFactory;
* it is the concrete subclass which creates concrete components.
*
* In this case, the abstract factory is a contract for creating some components
* for the web. There are two components : Text and Picture. There is two ways
* for the web. There are two components : Text and Picture. There are two ways
* of rendering : HTML or JSON.
*
* Therefore 4 concretes classes, but the client just need to know this contract
* to build a correct http response (for a html page or for an ajax request)
* Therefore 4 concrete classes, but the client just needs to know this contract
* to build a correct HTTP response (for a HTML page or for an AJAX request).
*/
abstract class AbstractFactory
{
/**
* Creates a text component
*
* Creates a text component.
*
* @param string $content
*
* @return Text
@@ -29,8 +29,8 @@ abstract class AbstractFactory
abstract public function createText($content);
/**
* Creates a picture component
*
* Creates a picture component.
*
* @param string $path
* @param string $name
*

View File

@@ -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
*/

View File

@@ -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>';
}
}

View File

@@ -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
*

View File

@@ -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
*/

View File

@@ -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
*/

View File

@@ -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
*

View File

@@ -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
*/

Some files were not shown because too many files have changed in this diff Show More