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

View File

@@ -3,7 +3,7 @@
namespace DesignPatterns\Structural\Adapter;
/**
* Book is a concrete and standard paper book
* Book is a concrete and standard paper book.
*/
class Book implements PaperBookInterface
{
@@ -12,7 +12,6 @@ class Book implements PaperBookInterface
*/
public function open()
{
}
/**
@@ -20,6 +19,5 @@ class Book implements PaperBookInterface
*/
public function turnPage()
{
}
}

View File

@@ -3,8 +3,8 @@
namespace DesignPatterns\Structural\Adapter;
/**
* EBookAdapter is an adapter to fit an e-book like a paper book
*
* EBookAdapter is an adapter to fit an e-book like a paper book.
*
* This is the adapter here. Notice it implements PaperBookInterface,
* therefore you don't have to change the code of the client which using paper book.
*/
@@ -16,7 +16,7 @@ class EBookAdapter implements PaperBookInterface
protected $eBook;
/**
* Notice the constructor, it "wraps" an electronic book
* Notice the constructor, it "wraps" an electronic book.
*
* @param EBookInterface $ebook
*/
@@ -26,7 +26,7 @@ class EBookAdapter implements PaperBookInterface
}
/**
* This class makes the proper translation from one interface to another
* This class makes the proper translation from one interface to another.
*/
public function open()
{
@@ -34,7 +34,7 @@ class EBookAdapter implements PaperBookInterface
}
/**
* turns pages
* turns pages.
*/
public function turnPage()
{

View File

@@ -3,19 +3,19 @@
namespace DesignPatterns\Structural\Adapter;
/**
* EBookInterface is a contract for an electronic book
* EBookInterface is a contract for an electronic book.
*/
interface EBookInterface
{
/**
* go to next page
* go to next page.
*
* @return mixed
*/
public function pressNext();
/**
* start the book
* start the book.
*
* @return mixed
*/

View File

@@ -3,7 +3,7 @@
namespace DesignPatterns\Structural\Adapter;
/**
* Kindle is a concrete electronic book
* Kindle is a concrete electronic book.
*/
class Kindle implements EBookInterface
{
@@ -12,7 +12,6 @@ class Kindle implements EBookInterface
*/
public function pressNext()
{
}
/**
@@ -20,6 +19,5 @@ class Kindle implements EBookInterface
*/
public function pressStart()
{
}
}

View File

@@ -3,19 +3,19 @@
namespace DesignPatterns\Structural\Adapter;
/**
* PaperBookInterface is a contract for a book
* PaperBookInterface is a contract for a book.
*/
interface PaperBookInterface
{
/**
* method to turn pages
* method to turn pages.
*
* @return mixed
*/
public function turnPage();
/**
* method to open the book
* method to open the book.
*
* @return mixed
*/

View File

@@ -1,14 +0,0 @@
# Adapter / Wrapper
## Purpose
To translate one interface for a class into a compatible interface. An adapter allows classes to work together that normally could not because of incompatible interfaces by providing it's interface to clients while using the original interface.
## Examples
* DB Client libraries adapter
* using multiple different webservices and adapters normalize data so that the outcome is the same for all
## UML Diagram
![Alt Adapter UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,71 @@
`Adapter / Wrapper`__
=====================
Purpose
-------
To translate one interface for a class into a compatible interface. An
adapter allows classes to work together that normally could not because
of incompatible interfaces by providing it's interface to clients while
using the original interface.
Examples
--------
- DB Client libraries adapter
- using multiple different webservices and adapters normalize data so
that the outcome is the same for all
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Adapter UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
PaperBookInterface.php
.. literalinclude:: PaperBookInterface.php
:language: php
:linenos:
Book.php
.. literalinclude:: Book.php
:language: php
:linenos:
EBookAdapter.php
.. literalinclude:: EBookAdapter.php
:language: php
:linenos:
EBookInterface.php
.. literalinclude:: EBookInterface.php
:language: php
:linenos:
Kindle.php
.. literalinclude:: Kindle.php
:language: php
:linenos:
Test
----
Tests/AdapterTest.php
.. literalinclude:: Tests/AdapterTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Structural/Adapter
.. __: http://en.wikipedia.org/wiki/Adapter_pattern

View File

@@ -2,14 +2,14 @@
namespace DesignPatterns\Structural\Adapter\Tests;
use DesignPatterns\Structural\Adapter\Book;
use DesignPatterns\Structural\Adapter\EBookAdapter;
use DesignPatterns\Structural\Adapter\Kindle;
use DesignPatterns\Structural\Adapter\PaperBookInterface;
use DesignPatterns\Structural\Adapter\Book;
/**
* AdapterTest shows the use of an adapted e-book that behave like a book
* You don't have to change the code of your client
* You don't have to change the code of your client.
*/
class AdapterTest extends \PHPUnit_Framework_TestCase
{
@@ -21,13 +21,13 @@ class AdapterTest extends \PHPUnit_Framework_TestCase
return array(
array(new Book()),
// we build a "wrapped" electronic book in the adapter
array(new EBookAdapter(new Kindle()))
array(new EBookAdapter(new Kindle())),
);
}
/**
* This client only knows paper book but surprise, surprise, the second book
* is in fact an electronic book, but both work the same way
* is in fact an electronic book, but both work the same way.
*
* @param PaperBookInterface $book
*
@@ -35,7 +35,7 @@ class AdapterTest extends \PHPUnit_Framework_TestCase
*/
public function testIAmAnOldClient(PaperBookInterface $book)
{
$book->open();
$book->turnPage();
$this->assertTrue(method_exists($book, 'open'));
$this->assertTrue(method_exists($book, 'turnPage'));
}
}

View File

@@ -4,9 +4,8 @@ namespace DesignPatterns\Structural\Bridge;
class Assemble implements Workshop
{
public function work()
{
print 'Assembled';
echo 'Assembled';
}
}

View File

@@ -3,11 +3,10 @@
namespace DesignPatterns\Structural\Bridge;
/**
* Refined Abstraction
* Refined Abstraction.
*/
class Car extends Vehicle
{
public function __construct(Workshop $workShop1, Workshop $workShop2)
{
parent::__construct($workShop1, $workShop2);
@@ -15,7 +14,7 @@ class Car extends Vehicle
public function manufacture()
{
print 'Car ';
echo 'Car ';
$this->workShop1->work();
$this->workShop2->work();
}

View File

@@ -3,11 +3,10 @@
namespace DesignPatterns\Structural\Bridge;
/**
* Refined Abstraction
* Refined Abstraction.
*/
class Motorcycle extends Vehicle
{
public function __construct(Workshop $workShop1, Workshop $workShop2)
{
parent::__construct($workShop1, $workShop2);
@@ -15,7 +14,7 @@ class Motorcycle extends Vehicle
public function manufacture()
{
print 'Motorcycle ';
echo 'Motorcycle ';
$this->workShop1->work();
$this->workShop2->work();
}

View File

@@ -3,13 +3,12 @@
namespace DesignPatterns\Structural\Bridge;
/**
* Concrete Implementation
* Concrete Implementation.
*/
class Produce implements Workshop
{
public function work()
{
print 'Produced ';
echo 'Produced ';
}
}

View File

@@ -1,12 +0,0 @@
## Purpose
Decouple an abstraction from its implementation so that the two can vary
independently. (http://en.wikipedia.org/wiki/Bridge_pattern)
#### Sample:
* [Symfony DoctrineBridge](https://github.com/symfony/DoctrineBridge)
## UML Diagram
![Alt Bridge UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,74 @@
`Bridge`__
==========
Purpose
-------
Decouple an abstraction from its implementation so that the two can vary
independently.
Sample:
^^^^^^^
- `Symfony
DoctrineBridge <https://github.com/symfony/DoctrineBridge>`__
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Bridge UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
Workshop.php
.. literalinclude:: Workshop.php
:language: php
:linenos:
Assemble.php
.. literalinclude:: Assemble.php
:language: php
:linenos:
Produce.php
.. literalinclude:: Produce.php
:language: php
:linenos:
Vehicle.php
.. literalinclude:: Vehicle.php
:language: php
:linenos:
Motorcycle.php
.. literalinclude:: Motorcycle.php
:language: php
:linenos:
Car.php
.. literalinclude:: Car.php
:language: php
:linenos:
Test
----
Tests/BridgeTest.php
.. literalinclude:: Tests/BridgeTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Structural/Bridge
.. __: http://en.wikipedia.org/wiki/Bridge_pattern

View File

@@ -9,7 +9,6 @@ use DesignPatterns\Structural\Bridge\Produce;
class BridgeTest extends \PHPUnit_Framework_TestCase
{
public function testCar()
{
$vehicle = new Car(new Produce(), new Assemble());

View File

@@ -3,11 +3,10 @@
namespace DesignPatterns\Structural\Bridge;
/**
* Abstraction
* Abstraction.
*/
abstract class Vehicle
{
protected $workShop1;
protected $workShop2;

View File

@@ -3,10 +3,9 @@
namespace DesignPatterns\Structural\Bridge;
/**
* Implementer
* Implementer.
*/
interface Workshop
{
public function work();
}

View File

@@ -15,7 +15,7 @@ class Form extends FormElement
/**
* runs through all elements and calls render() on them, then returns the complete representation
* of the form
* of the form.
*
* from the outside, one will not see this and the form will act like a single object instance
*
@@ -28,7 +28,7 @@ class Form extends FormElement
$formCode = '';
foreach ($this->elements as $element) {
$formCode .= $element->render($indent + 1) . PHP_EOL;
$formCode .= $element->render($indent + 1).PHP_EOL;
}
return $formCode;

View File

@@ -3,12 +3,12 @@
namespace DesignPatterns\Structural\Composite;
/**
* Class FormElement
* Class FormElement.
*/
abstract class FormElement
{
/**
* renders the elements' code
* renders the elements' code.
*
* @param int $indent
*

View File

@@ -3,12 +3,12 @@
namespace DesignPatterns\Structural\Composite;
/**
* Class InputElement
* Class InputElement.
*/
class InputElement extends FormElement
{
/**
* renders the input element HTML
* renders the input element HTML.
*
* @param int $indent
*
@@ -16,6 +16,6 @@ class InputElement extends FormElement
*/
public function render($indent = 0)
{
return str_repeat(' ', $indent) . '<input type="text" />';
return str_repeat(' ', $indent).'<input type="text" />';
}
}

View File

@@ -1,15 +0,0 @@
# Composite
# Purpose
To treat a group of objects the same way as a single instance of the object.
# Examples
* a form class instance handles all its form elements like a single instance of the form, when `render()` is called, it
subsequently runs through all its child elements and calls `render()` on them
* `Zend_Config`: a tree of configuration options, each one is a `Zend_Config` object itself
## UML Diagram
![Alt Composite UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,65 @@
`Composite`__
=============
Purpose
-------
To treat a group of objects the same way as a single instance of the
object.
Examples
--------
- a form class instance handles all its form elements like a single
instance of the form, when ``render()`` is called, it subsequently
runs through all its child elements and calls ``render()`` on them
- ``Zend_Config``: a tree of configuration options, each one is a
``Zend_Config`` object itself
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Composite UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
FormElement.php
.. literalinclude:: FormElement.php
:language: php
:linenos:
Form.php
.. literalinclude:: Form.php
:language: php
:linenos:
InputElement.php
.. literalinclude:: InputElement.php
:language: php
:linenos:
TextElement.php
.. literalinclude:: TextElement.php
:language: php
:linenos:
Test
----
Tests/CompositeTest.php
.. literalinclude:: Tests/CompositeTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Structural/Composite
.. __: http://en.wikipedia.org/wiki/Composite_pattern

View File

@@ -1,15 +1,14 @@
<?php
namespace DesignPatterns\Test\Composite\Tests;
namespace DesignPatterns\Structural\Composite\Tests;
use DesignPatterns\Structural\Composite;
/**
* FormTest tests the composite pattern on Form
* FormTest tests the composite pattern on Form.
*/
class CompositeTest extends \PHPUnit_Framework_TestCase
{
public function testRender()
{
$form = new Composite\Form();
@@ -25,7 +24,7 @@ class CompositeTest extends \PHPUnit_Framework_TestCase
/**
* The all point of this pattern, a Composite must inherit from the node
* if you want to builld trees
* if you want to builld trees.
*/
public function testFormImplementsFormEelement()
{

View File

@@ -3,12 +3,12 @@
namespace DesignPatterns\Structural\Composite;
/**
* Class TextElement
* Class TextElement.
*/
class TextElement extends FormElement
{
/**
* renders the text element
* renders the text element.
*
* @param int $indent
*
@@ -16,6 +16,6 @@ class TextElement extends FormElement
*/
public function render($indent = 0)
{
return str_repeat(' ', $indent) . 'this is a text element';
return str_repeat(' ', $indent).'this is a text element';
}
}

View File

@@ -1,22 +0,0 @@
# Data Mapper
## Purpose
A Data Mapper, is a Data Access Layer that performs bidirectional transfer of
data between a persistent data store (often a relational database) and an in
memory data representation (the domain layer). The goal of the pattern is to
keep the in memory representation and the persistent data store independent of
each other and the data mapper itself. The layer is composed of one or more
mappers (or Data Access Objects), performing the data transfer. Mapper
implementations vary in scope. Generic mappers will handle many different domain
entity types, dedicated mappers will handle one or a few.
The key point of this pattern is, unlike Active Record pattern, the data model follows Single Responsibility Principle.
## Examples
* DB Object Relational Mapper (ORM) : Doctrine2 uses DAO named as "EntityRepository"
## UML Diagram
![Alt DataMapper UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,60 @@
`Data Mapper`__
===============
Purpose
-------
A Data Mapper, is a Data Access Layer that performs bidirectional
transfer of data between a persistent data store (often a relational
database) and an in memory data representation (the domain layer). The
goal of the pattern is to keep the in memory representation and the
persistent data store independent of each other and the data mapper
itself. The layer is composed of one or more mappers (or Data Access
Objects), performing the data transfer. Mapper implementations vary in
scope. Generic mappers will handle many different domain entity types,
dedicated mappers will handle one or a few.
The key point of this pattern is, unlike Active Record pattern, the data
model follows Single Responsibility Principle.
Examples
--------
- DB Object Relational Mapper (ORM) : Doctrine2 uses DAO named as
"EntityRepository"
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt DataMapper UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
User.php
.. literalinclude:: User.php
:language: php
:linenos:
UserMapper.php
.. literalinclude:: UserMapper.php
:language: php
:linenos:
Test
----
Tests/DataMapperTest.php
.. literalinclude:: Tests/DataMapperTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Structural/DataMapper
.. __: http://en.wikipedia.org/wiki/Data_mapper_pattern

View File

@@ -2,11 +2,11 @@
namespace DesignPatterns\Structural\DataMapper\Tests;
use DesignPatterns\Structural\DataMapper\UserMapper;
use DesignPatterns\Structural\DataMapper\User;
use DesignPatterns\Structural\DataMapper\UserMapper;
/**
* UserMapperTest tests the datamapper pattern
* UserMapperTest tests the datamapper pattern.
*/
class DataMapperTest extends \PHPUnit_Framework_TestCase
{
@@ -66,9 +66,9 @@ class DataMapperTest extends \PHPUnit_Framework_TestCase
public function testRestoreOne(User $existing)
{
$row = array(
'userid' => 1,
'userid' => 1,
'username' => 'Odysseus',
'email' => 'Odysseus@ithaca.gr'
'email' => 'Odysseus@ithaca.gr',
);
$rows = new \ArrayIterator(array($row));
$this->dbal->expects($this->once())

View File

@@ -3,12 +3,11 @@
namespace DesignPatterns\Structural\DataMapper;
/**
* DataMapper pattern
* DataMapper pattern.
*
* This is our representation of a DataBase record in the memory (Entity)
*
* Validation would also go in this object
*
*/
class User
{

View File

@@ -3,7 +3,7 @@
namespace DesignPatterns\Structural\DataMapper;
/**
* class UserMapper
* class UserMapper.
*/
class UserMapper
{
@@ -21,19 +21,19 @@ class UserMapper
}
/**
* saves a user object from memory to Database
* saves a user object from memory to Database.
*
* @param User $user
*
* @return boolean
* @return bool
*/
public function save(User $user)
{
/* $data keys should correspond to valid Table columns on the Database */
$data = array(
'userid' => $user->getUserId(),
'userid' => $user->getUserId(),
'username' => $user->getUsername(),
'email' => $user->getEmail(),
'email' => $user->getEmail(),
);
/* if no ID specified create new user else update the one in the Database */
@@ -51,11 +51,12 @@ class UserMapper
/**
* finds a user from Database based on ID and returns a User object located
* in memory
* in memory.
*
* @param int $id
*
* @throws \InvalidArgumentException
*
* @return User
*/
public function findById($id)
@@ -72,14 +73,14 @@ class UserMapper
/**
* fetches an array from Database and returns an array of User objects
* located in memory
* located in memory.
*
* @return array
*/
public function findAll()
{
$resultSet = $this->adapter->findAll();
$entries = array();
$entries = array();
foreach ($resultSet as $row) {
$entries[] = $this->mapObject($row);
@@ -89,7 +90,7 @@ class UserMapper
}
/**
* Maps a table row to an object
* Maps a table row to an object.
*
* @param array $row
*

View File

@@ -9,7 +9,7 @@ namespace DesignPatterns\Structural\Decorator;
*/
/**
* class Decorator
* class Decorator.
*/
abstract class Decorator implements RendererInterface
{
@@ -21,7 +21,7 @@ abstract class Decorator implements RendererInterface
/**
* You must type-hint the wrapped component :
* It ensures you can call renderData() in the subclasses !
*
*
* @param RendererInterface $wrappable
*/
public function __construct(RendererInterface $wrappable)

View File

@@ -1,14 +0,0 @@
# Decorator
## Purpose
To dynamically add new functionality to class instances.
## Examples
* Zend Framework: decorators for `Zend_Form_Element` instances
* Web Service Layer: Decorators JSON and XML for a REST service (in this case, only one of these should be allowed of course)
## UML Diagram
![Alt Decorator UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,68 @@
`Decorator`__
=============
Purpose
-------
To dynamically add new functionality to class instances.
Examples
--------
- Zend Framework: decorators for ``Zend_Form_Element`` instances
- Web Service Layer: Decorators JSON and XML for a REST service (in
this case, only one of these should be allowed of course)
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Decorator UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
RendererInterface.php
.. literalinclude:: RendererInterface.php
:language: php
:linenos:
Webservice.php
.. literalinclude:: Webservice.php
:language: php
:linenos:
Decorator.php
.. literalinclude:: Decorator.php
:language: php
:linenos:
RenderInXml.php
.. literalinclude:: RenderInXml.php
:language: php
:linenos:
RenderInJson.php
.. literalinclude:: RenderInJson.php
:language: php
:linenos:
Test
----
Tests/DecoratorTest.php
.. literalinclude:: Tests/DecoratorTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Structural/Decorator
.. __: http://en.wikipedia.org/wiki/Decorator_pattern

View File

@@ -3,12 +3,12 @@
namespace DesignPatterns\Structural\Decorator;
/**
* Class RenderInJson
* Class RenderInJson.
*/
class RenderInJson extends Decorator
{
/**
* render data as JSON
* render data as JSON.
*
* @return mixed|string
*/

View File

@@ -3,12 +3,12 @@
namespace DesignPatterns\Structural\Decorator;
/**
* Class RenderInXml
* Class RenderInXml.
*/
class RenderInXml extends Decorator
{
/**
* render data as XML
* render data as XML.
*
* @return mixed|string
*/

View File

@@ -3,12 +3,12 @@
namespace DesignPatterns\Structural\Decorator;
/**
* Class RendererInterface
* Class RendererInterface.
*/
interface RendererInterface
{
/**
* render data
* render data.
*
* @return mixed
*/

View File

@@ -5,11 +5,10 @@ namespace DesignPatterns\Structural\Decorator\Tests;
use DesignPatterns\Structural\Decorator;
/**
* DecoratorTest tests the decorator pattern
* DecoratorTest tests the decorator pattern.
*/
class DecoratorTest extends \PHPUnit_Framework_TestCase
{
protected $service;
protected function setUp()
@@ -27,7 +26,7 @@ class DecoratorTest extends \PHPUnit_Framework_TestCase
public function testXmlDecorator()
{
// Wrap service with a JSON decorator for renderers
// Wrap service with a XML decorator for renderers
$service = new Decorator\RenderInXml($this->service);
// Our Renderer will now output XML instead of an array
$xml = '<?xml version="1.0"?><foo>bar</foo>';
@@ -35,7 +34,7 @@ class DecoratorTest extends \PHPUnit_Framework_TestCase
}
/**
* The first key-point of this pattern :
* The first key-point of this pattern :.
*/
public function testDecoratorMustImplementsRenderer()
{
@@ -45,17 +44,32 @@ class DecoratorTest extends \PHPUnit_Framework_TestCase
}
/**
* Second key-point of this pattern : the decorator is type-hinted
*
* Second key-point of this pattern : the decorator is type-hinted.
*
* @expectedException \PHPUnit_Framework_Error
*/
public function testDecoratorTypeHinted()
{
if (version_compare(PHP_VERSION, '7', '>=')) {
throw new \PHPUnit_Framework_Error('Skip test for PHP 7', 0, __FILE__, __LINE__);
}
$this->getMockForAbstractClass('DesignPatterns\Structural\Decorator\Decorator', array(new \stdClass()));
}
/**
* Second key-point of this pattern : the decorator is type-hinted.
*
* @requires PHP 7
* @expectedException TypeError
*/
public function testDecoratorTypeHintedForPhp7()
{
$this->getMockForAbstractClass('DesignPatterns\Structural\Decorator\Decorator', array(new \stdClass()));
}
/**
* The decorator implements and wraps the same interface
* The decorator implements and wraps the same interface.
*/
public function testDecoratorOnlyAcceptRenderer()
{

View File

@@ -3,7 +3,7 @@
namespace DesignPatterns\Structural\Decorator;
/**
* Class Webservice
* Class Webservice.
*/
class Webservice implements RendererInterface
{

View File

@@ -3,7 +3,7 @@
namespace DesignPatterns\Structural\DependencyInjection;
/**
* class AbstractConfig
* class AbstractConfig.
*/
abstract class AbstractConfig
{

View File

@@ -3,17 +3,18 @@
namespace DesignPatterns\Structural\DependencyInjection;
/**
* class ArrayConfig
* class ArrayConfig.
*
* uses array as data source
*/
class ArrayConfig extends AbstractConfig implements Parameters
{
/**
* Get parameter
* Get parameter.
*
* @param string|int $key
* @param null $default
* @param null $default
*
* @return mixed
*/
public function get($key, $default = null)
@@ -21,14 +22,15 @@ class ArrayConfig extends AbstractConfig implements Parameters
if (isset($this->storage[$key])) {
return $this->storage[$key];
}
return $default;
}
/**
* Set parameter
* Set parameter.
*
* @param string|int $key
* @param mixed $value
* @param mixed $value
*/
public function set($key, $value)
{

View File

@@ -3,7 +3,7 @@
namespace DesignPatterns\Structural\DependencyInjection;
/**
* Class Connection
* Class Connection.
*/
class Connection
{
@@ -26,7 +26,7 @@ class Connection
}
/**
* connection using the injected config
* connection using the injected config.
*/
public function connect()
{
@@ -42,6 +42,7 @@ class Connection
*
* @return string
*/
public function getHost()
{
return $this->host;

View File

@@ -3,12 +3,12 @@
namespace DesignPatterns\Structural\DependencyInjection;
/**
* Parameters interface
* Parameters interface.
*/
interface Parameters
{
/**
* Get parameter
* Get parameter.
*
* @param string|int $key
*
@@ -17,7 +17,7 @@ interface Parameters
public function get($key);
/**
* Set parameter
* Set parameter.
*
* @param string|int $key
* @param mixed $value

View File

@@ -1,20 +0,0 @@
# Dependency Injection
## Purpose
To implement a loosely coupled architecture in order to get better testable, maintainable and extendable code.
## Usage
Configuration gets injected and `Connection` will get all that it needs from `$config`. Without DI, the configuration would be created directly in `Connection`, which is not very good for testing and extending `Connection`.
Notice we are following Inversion of control principle in `Connection` by asking `$config` to implement `Parameters` interface. This decouples our components. We don't care where the source of information comes from, we only care that `$config` has certain methods to retrieve that information. Read more about Inversion of control [here](http://en.wikipedia.org/wiki/Inversion_of_control).
## Examples
* The Doctrine2 ORM uses dependency injection e.g. for configuration that is injected into a `Connection` object. For testing purposes, one can easily create a mock object of the configuration and inject that into the `Connection` object
* Symfony and Zend Framework 2 already have containers for DI that create objects via a configuration array and inject them where needed (i.e. in Controllers)
## UML Diagram
![Alt DependencyInjection UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,88 @@
`Dependency Injection`__
========================
Purpose
-------
To implement a loosely coupled architecture in order to get better
testable, maintainable and extendable code.
Usage
-----
Configuration gets injected and ``Connection`` will get all that it
needs from ``$config``. Without DI, the configuration would be created
directly in ``Connection``, which is not very good for testing and
extending ``Connection``.
Notice we are following Inversion of control principle in ``Connection``
by asking ``$config`` to implement ``Parameters`` interface. This
decouples our components. We don't care where the source of information
comes from, we only care that ``$config`` has certain methods to
retrieve that information. Read more about Inversion of control
`here <http://en.wikipedia.org/wiki/Inversion_of_control>`__.
Examples
--------
- The Doctrine2 ORM uses dependency injection e.g. for configuration
that is injected into a ``Connection`` object. For testing purposes,
one can easily create a mock object of the configuration and inject
that into the ``Connection`` object
- Symfony and Zend Framework 2 already have containers for DI that
create objects via a configuration array and inject them where needed
(i.e. in Controllers)
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt DependencyInjection UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
AbstractConfig.php
.. literalinclude:: AbstractConfig.php
:language: php
:linenos:
Parameters.php
.. literalinclude:: Parameters.php
:language: php
:linenos:
ArrayConfig.php
.. literalinclude:: ArrayConfig.php
:language: php
:linenos:
Connection.php
.. literalinclude:: Connection.php
:language: php
:linenos:
Test
----
Tests/DependencyInjectionTest.php
.. literalinclude:: Tests/DependencyInjectionTest.php
:language: php
:linenos:
Tests/config.php
.. literalinclude:: Tests/config.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Structural/DependencyInjection
.. __: http://en.wikipedia.org/wiki/Dependency_injection

View File

@@ -3,29 +3,29 @@
namespace DesignPatterns\Structural\Facade;
/**
* Class BiosInterface
* Interface BiosInterface.
*/
interface BiosInterface
{
/**
* execute the BIOS
* Execute the BIOS.
*/
public function execute();
/**
* wait for halt
* Wait for halt.
*/
public function waitForKeyPress();
/**
* launches the OS
* Launches the OS.
*
* @param OsInterface $os
*/
public function launch(OsInterface $os);
/**
* power down BIOS
* Power down BIOS.
*/
public function powerDown();
}

View File

@@ -3,8 +3,7 @@
namespace DesignPatterns\Structural\Facade;
/**
*
*
* Class Facade.
*/
class Facade
{
@@ -20,7 +19,7 @@ class Facade
/**
* This is the perfect time to use a dependency injection container
* to create an instance of this class
* to create an instance of this class.
*
* @param BiosInterface $bios
* @param OsInterface $os
@@ -32,7 +31,7 @@ class Facade
}
/**
* turn on the system
* Turn on the system.
*/
public function turnOn()
{
@@ -42,7 +41,7 @@ class Facade
}
/**
* turn off the system
* Turn off the system.
*/
public function turnOff()
{

View File

@@ -3,12 +3,12 @@
namespace DesignPatterns\Structural\Facade;
/**
* Class OsInterface
* Interface OsInterface.
*/
interface OsInterface
{
/**
* halt the OS
* Halt the OS.
*/
public function halt();
}

View File

@@ -1,21 +0,0 @@
# Facade
## Purpose
The primary goal of a Facade Pattern is not to avoid you to read the manual of a complex API. It's only a side-effect.
The first goal is to reduce coupling and follow the Law of Demeter.
A Facade is meant to decouple a client and a sub-system by embedding many (but sometimes just one) interface, and of course to reduce complexity.
* A facade does not forbid you the access to the sub-system
* You can (you should) have multiple facades for one sub-system
That's why a good facade has no `new` in it. If there are multiple creations for each method, it is not a Facade, it's a Builder or a
[Abstract|Static|Simple] Factory [Method].
The best facade has no `new` and a constructor with interface-type-hinted parameters.
If you need creation of new instances, use a Factory as argument.
## UML Diagram
![Alt Facade UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,66 @@
`Facade`__
==========
Purpose
-------
The primary goal of a Facade Pattern is not to avoid you to read the
manual of a complex API. It's only a side-effect. The first goal is to
reduce coupling and follow the Law of Demeter.
A Facade is meant to decouple a client and a sub-system by embedding
many (but sometimes just one) interface, and of course to reduce
complexity.
- A facade does not forbid you the access to the sub-system
- You can (you should) have multiple facades for one sub-system
That's why a good facade has no ``new`` in it. If there are multiple
creations for each method, it is not a Facade, it's a Builder or a
[Abstract\|Static\|Simple] Factory [Method].
The best facade has no ``new`` and a constructor with
interface-type-hinted parameters. If you need creation of new instances,
use a Factory as argument.
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Facade UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
Facade.php
.. literalinclude:: Facade.php
:language: php
:linenos:
OsInterface.php
.. literalinclude:: OsInterface.php
:language: php
:linenos:
BiosInterface.php
.. literalinclude:: BiosInterface.php
:language: php
:linenos:
Test
----
Tests/FacadeTest.php
.. literalinclude:: Tests/FacadeTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Structural/Facade
.. __: http://en.wikipedia.org/wiki/Facade_pattern

View File

@@ -3,13 +3,13 @@
namespace DesignPatterns\Structural\Facade\Tests;
use DesignPatterns\Structural\Facade\Facade as Computer;
use DesignPatterns\Structural\Facade\OsInterface;
/**
* FacadeTest shows example of facades
* FacadeTest shows example of facades.
*/
class FacadeTest extends \PHPUnit_Framework_TestCase
{
public function getComputer()
{
$bios = $this->getMockBuilder('DesignPatterns\Structural\Facade\BiosInterface')
@@ -29,13 +29,16 @@ class FacadeTest extends \PHPUnit_Framework_TestCase
->will($this->returnValue('Linux'));
$facade = new Computer($bios, $operatingSys);
return array(array($facade, $operatingSys));
}
/**
* @param Computer $facade
* @param OsInterface $os
* @dataProvider getComputer
*/
public function testComputerOn(Computer $facade, $os)
public function testComputerOn(Computer $facade, OsInterface $os)
{
// interface is simpler :
$facade->turnOn();

View File

@@ -1,15 +0,0 @@
# Fluent Interface
## Purpose
To write code that is easy readable just like sentences in a natural language (like English).
## Examples
* Doctrine2's QueryBuilder works something like that example class below
* PHPUnit uses fluent interfaces to build mock objects
* Yii Framework: CDbCommand and CActiveRecord use this pattern, too
## UML Diagram
![Alt FluentInterface UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,46 @@
`Fluent Interface`__
====================
Purpose
-------
To write code that is easy readable just like sentences in a natural
language (like English).
Examples
--------
- Doctrine2's QueryBuilder works something like that example class
below
- PHPUnit uses fluent interfaces to build mock objects
- Yii Framework: CDbCommand and CActiveRecord use this pattern, too
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt FluentInterface UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
Sql.php
.. literalinclude:: Sql.php
:language: php
:linenos:
Test
----
Tests/FluentInterfaceTest.php
.. literalinclude:: Tests/FluentInterfaceTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Structural/FluentInterface
.. __: http://en.wikipedia.org/wiki/Fluent_interface

View File

@@ -3,7 +3,7 @@
namespace DesignPatterns\Structural\FluentInterface;
/**
* class SQL
* class SQL.
*/
class Sql
{
@@ -23,7 +23,7 @@ class Sql
protected $where = array();
/**
* adds select fields
* adds select fields.
*
* @param array $fields
*
@@ -37,7 +37,7 @@ class Sql
}
/**
* adds a FROM clause
* adds a FROM clause.
*
* @param string $table
* @param string $alias
@@ -46,13 +46,13 @@ class Sql
*/
public function from($table, $alias)
{
$this->from[] = $table . ' AS ' . $alias;
$this->from[] = $table.' AS '.$alias;
return $this;
}
/**
* adds a WHERE condition
* adds a WHERE condition.
*
* @param string $condition
*
@@ -66,15 +66,15 @@ class Sql
}
/**
* Gets the query, just an example of building a query,
* no check on consistency
* Gets the query, just an example of building a query,
* no check on consistency.
*
* @return string
*/
public function getQuery()
{
return 'SELECT ' . implode(',', $this->fields)
. ' FROM ' . implode(',', $this->from)
. ' WHERE ' . implode(' AND ', $this->where);
return 'SELECT '.implode(',', $this->fields)
.' FROM '.implode(',', $this->from)
.' WHERE '.implode(' AND ', $this->where);
}
}

View File

@@ -5,11 +5,10 @@ namespace DesignPatterns\Structural\FluentInterface\Tests;
use DesignPatterns\Structural\FluentInterface\Sql;
/**
* FluentInterfaceTest tests the fluent interface SQL
* FluentInterfaceTest tests the fluent interface SQL.
*/
class FluentInterfaceTest extends \PHPUnit_Framework_TestCase
{
public function testBuildSQL()
{
$instance = new Sql();

View File

@@ -1,13 +0,0 @@
# Proxy
## Purpose
To interface to anything that is expensive or impossible to duplicate.
## Examples
* Doctrine2 uses proxies to implement framework magic (e.g. lazy initialization) in them, while the user still works with his own entity classes and will never use nor touch the proxies
## UML Diagram
![Alt Proxy UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,44 @@
`Proxy`__
=========
Purpose
-------
To interface to anything that is expensive or impossible to duplicate.
Examples
--------
- Doctrine2 uses proxies to implement framework magic (e.g. lazy
initialization) in them, while the user still works with his own
entity classes and will never use nor touch the proxies
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Proxy UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
Record.php
.. literalinclude:: Record.php
:language: php
:linenos:
RecordProxy.php
.. literalinclude:: RecordProxy.php
:language: php
:linenos:
Test
----
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Structural/Proxy
.. __: http://en.wikipedia.org/wiki/Proxy_pattern

View File

@@ -3,7 +3,7 @@
namespace DesignPatterns\Structural\Proxy;
/**
* class Record
* class Record.
*/
class Record
{
@@ -21,7 +21,7 @@ class Record
}
/**
* magic setter
* magic setter.
*
* @param string $name
* @param mixed $value
@@ -34,7 +34,7 @@ class Record
}
/**
* magic getter
* magic getter.
*
* @param string $name
*
@@ -45,7 +45,7 @@ class Record
if (array_key_exists($name, $this->data)) {
return $this->data[(string) $name];
} else {
return null;
return;
}
}
}

View File

@@ -3,7 +3,7 @@
namespace DesignPatterns\Structural\Proxy;
/**
* Class RecordProxy
* Class RecordProxy.
*/
class RecordProxy extends Record
{
@@ -35,7 +35,7 @@ class RecordProxy extends Record
}
/**
* magic setter
* magic setter.
*
* @param string $name
* @param mixed $value

22
Structural/README.rst Normal file
View File

@@ -0,0 +1,22 @@
`Structural`__
==============
In Software Engineering, Structural Design Patterns are Design Patterns
that ease the design by identifying a simple way to realize
relationships between entities.
.. toctree::
:titlesonly:
Adapter/README
Bridge/README
Composite/README
DataMapper/README
Decorator/README
DependencyInjection/README
Facade/README
FluentInterface/README
Proxy/README
Registry/README
.. __: http://en.wikipedia.org/wiki/Structural_pattern

View File

@@ -1,15 +0,0 @@
# Registry
## Purpose
To implement a central storage for objects often used throughout the application, is typically implemented using
an abstract class with only static methods (or using the Singleton pattern)
## Examples
* Zend Framework: `Zend_Registry` holds the application's logger object, front controller etc.
* Yii Framework: `CWebApplication` holds all the application components, such as `CWebUser`, `CUrlManager`, etc.
## UML Diagram
![Alt Registry UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,47 @@
`Registry`__
============
Purpose
-------
To implement a central storage for objects often used throughout the
application, is typically implemented using an abstract class with only
static methods (or using the Singleton pattern)
Examples
--------
- Zend Framework 1: ``Zend_Registry`` holds the application's logger
object, front controller etc.
- Yii Framework: ``CWebApplication`` holds all the application
components, such as ``CWebUser``, ``CUrlManager``, etc.
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Registry UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
Registry.php
.. literalinclude:: Registry.php
:language: php
:linenos:
Test
----
Tests/RegistryTest.php
.. literalinclude:: Tests/RegistryTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Structural/Registry
.. __: http://en.wikipedia.org/wiki/Service_locator_pattern

View File

@@ -3,7 +3,7 @@
namespace DesignPatterns\Structural\Registry;
/**
* class Registry
* class Registry.
*/
abstract class Registry
{
@@ -15,12 +15,13 @@ abstract class Registry
protected static $storedValues = array();
/**
* sets a value
* sets a value.
*
* @param string $key
* @param mixed $value
*
* @static
*
* @return void
*/
public static function set($key, $value)
@@ -29,11 +30,12 @@ abstract class Registry
}
/**
* gets a value from the registry
* gets a value from the registry.
*
* @param string $key
*
* @static
*
* @return mixed
*/
public static function get($key)

View File

@@ -6,12 +6,15 @@ use DesignPatterns\Structural\Registry\Registry;
class RegistryTest extends \PHPUnit_Framework_TestCase
{
public function testSetAndGetLogger()
{
Registry::set(Registry::LOGGER, new \StdClass());
$key = Registry::LOGGER;
$object = new \StdClass();
$logger = Registry::get(Registry::LOGGER);
$this->assertInstanceOf('StdClass', $logger);
Registry::set($key, $object);
$actual = Registry::get($key);
$this->assertEquals($object, $actual);
$this->assertInstanceOf('StdClass', $actual);
}
}