mirror of
https://github.com/DesignPatternsPHP/DesignPatternsPHP.git
synced 2025-09-25 22:09:23 +02:00
Merge branch 'master' into flyweight
This commit is contained in:
@@ -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()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -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()
|
||||
{
|
||||
|
@@ -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
|
||||
*/
|
||||
|
@@ -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()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
*/
|
||||
|
@@ -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
|
||||
|
||||

|
71
Structural/Adapter/README.rst
Normal file
71
Structural/Adapter/README.rst
Normal 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
|
@@ -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'));
|
||||
}
|
||||
}
|
||||
|
@@ -4,9 +4,8 @@ namespace DesignPatterns\Structural\Bridge;
|
||||
|
||||
class Assemble implements Workshop
|
||||
{
|
||||
|
||||
public function work()
|
||||
{
|
||||
print 'Assembled';
|
||||
echo 'Assembled';
|
||||
}
|
||||
}
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -3,13 +3,12 @@
|
||||
namespace DesignPatterns\Structural\Bridge;
|
||||
|
||||
/**
|
||||
* Concrete Implementation
|
||||
* Concrete Implementation.
|
||||
*/
|
||||
class Produce implements Workshop
|
||||
{
|
||||
|
||||
public function work()
|
||||
{
|
||||
print 'Produced ';
|
||||
echo 'Produced ';
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
||||

|
74
Structural/Bridge/README.rst
Normal file
74
Structural/Bridge/README.rst
Normal 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
|
@@ -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());
|
||||
|
@@ -3,11 +3,10 @@
|
||||
namespace DesignPatterns\Structural\Bridge;
|
||||
|
||||
/**
|
||||
* Abstraction
|
||||
* Abstraction.
|
||||
*/
|
||||
abstract class Vehicle
|
||||
{
|
||||
|
||||
protected $workShop1;
|
||||
protected $workShop2;
|
||||
|
||||
|
@@ -3,10 +3,9 @@
|
||||
namespace DesignPatterns\Structural\Bridge;
|
||||
|
||||
/**
|
||||
* Implementer
|
||||
* Implementer.
|
||||
*/
|
||||
interface Workshop
|
||||
{
|
||||
|
||||
public function work();
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
*
|
||||
|
@@ -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" />';
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
||||

|
65
Structural/Composite/README.rst
Normal file
65
Structural/Composite/README.rst
Normal 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
|
@@ -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()
|
||||
{
|
||||
|
@@ -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';
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
||||

|
60
Structural/DataMapper/README.rst
Normal file
60
Structural/DataMapper/README.rst
Normal 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
|
@@ -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())
|
||||
|
@@ -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
|
||||
{
|
||||
|
@@ -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
|
||||
*
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
||||

|
68
Structural/Decorator/README.rst
Normal file
68
Structural/Decorator/README.rst
Normal 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
|
@@ -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
|
||||
*/
|
||||
|
@@ -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
|
||||
*/
|
||||
|
@@ -3,12 +3,12 @@
|
||||
namespace DesignPatterns\Structural\Decorator;
|
||||
|
||||
/**
|
||||
* Class RendererInterface
|
||||
* Class RendererInterface.
|
||||
*/
|
||||
interface RendererInterface
|
||||
{
|
||||
/**
|
||||
* render data
|
||||
* render data.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
|
@@ -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()
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Structural\Decorator;
|
||||
|
||||
/**
|
||||
* Class Webservice
|
||||
* Class Webservice.
|
||||
*/
|
||||
class Webservice implements RendererInterface
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace DesignPatterns\Structural\DependencyInjection;
|
||||
|
||||
/**
|
||||
* class AbstractConfig
|
||||
* class AbstractConfig.
|
||||
*/
|
||||
abstract class AbstractConfig
|
||||
{
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
||||

|
88
Structural/DependencyInjection/README.rst
Normal file
88
Structural/DependencyInjection/README.rst
Normal 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
|
@@ -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();
|
||||
}
|
||||
|
@@ -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()
|
||||
{
|
||||
|
@@ -3,12 +3,12 @@
|
||||
namespace DesignPatterns\Structural\Facade;
|
||||
|
||||
/**
|
||||
* Class OsInterface
|
||||
* Interface OsInterface.
|
||||
*/
|
||||
interface OsInterface
|
||||
{
|
||||
/**
|
||||
* halt the OS
|
||||
* Halt the OS.
|
||||
*/
|
||||
public function halt();
|
||||
}
|
||||
|
@@ -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
|
||||
|
||||

|
66
Structural/Facade/README.rst
Normal file
66
Structural/Facade/README.rst
Normal 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
|
@@ -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();
|
||||
|
@@ -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
|
||||
|
||||

|
46
Structural/FluentInterface/README.rst
Normal file
46
Structural/FluentInterface/README.rst
Normal 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
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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();
|
||||
|
@@ -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
|
||||
|
||||

|
44
Structural/Proxy/README.rst
Normal file
44
Structural/Proxy/README.rst
Normal 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
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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
22
Structural/README.rst
Normal 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
|
@@ -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
|
||||
|
||||

|
47
Structural/Registry/README.rst
Normal file
47
Structural/Registry/README.rst
Normal 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
|
@@ -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)
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user