Merge pull request #131 from shangguokan/read-the-docs

DesignPatternsPHP available on Read the Docs
This commit is contained in:
Dominik Liebler
2015-04-09 09:06:24 +02:00
80 changed files with 3169 additions and 550 deletions

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@
.idea
/nbproject
/vendor/
_build/

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,15 +0,0 @@
# Mediator
## Purpose
This pattern provides an easy to decouple many components working together.
It is a good alternative over Observer IF you have a "central intelligence",
like a controller (but not in the sense of the MVC).
All components (called Colleague) are only coupled to the MediatorInterface and
it is a good thing because in OOP, one good friend is better than many. This
is the key-feature of this pattern.
## UML Diagram
![Alt Mediator UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,73 @@
`Mediator`_
===========
Purpose
-------
This pattern provides an easy to decouple many components working
together. It is a good alternative over Observer IF you have a "central
intelligence", like a controller (but not in the sense of the MVC).
All components (called Colleague) are only coupled to the
MediatorInterface and it is a good thing because in OOP, one good friend
is better than many. This is the key-feature of this pattern.
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Mediator UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
MediatorInterface.php
.. literalinclude:: MediatorInterface.php
:language: php
:linenos:
Mediator.php
.. literalinclude:: Mediator.php
:language: php
:linenos:
Colleague.php
.. literalinclude:: Colleague.php
:language: php
:linenos:
Subsystem/Client.php
.. literalinclude:: Subsystem/Client.php
:language: php
:linenos:
Subsystem/Database.php
.. literalinclude:: Subsystem/Database.php
:language: php
:linenos:
Subsystem/Server.php
.. literalinclude:: Subsystem/Server.php
:language: php
:linenos:
Test
----
Tests/MediatorTest.php
.. literalinclude:: Tests/MediatorTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Behavioral/Mediator
.. _`Mediator`: http://en.wikipedia.org/wiki/Mediator_pattern

View File

@@ -1,22 +0,0 @@
# Memento
## Purpose
Provide the ability to restore an object to its previous state (undo via rollback).
The memento pattern is implemented with three objects: the originator, a caretaker and a memento.
The originator is some object that has an internal state.
The caretaker is going to do something to the originator, but wants to be able to undo the change.
The caretaker first asks the originator for a memento object. Then it does whatever operation (or sequence of operations) it was going to do.
To roll back to the state before the operations, it returns the memento object to the originator.
The memento object itself is an opaque object (one which the caretaker cannot, or should not, change).
When using this pattern, care should be taken if the originator may change other objects or resources - the memento pattern operates on a single object.
## Examples
* The seed of a pseudorandom number generator
* The state in a finite state machine
## UML Diagram
![Alt Momento UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,68 @@
`Memento`_
==========
Purpose
-------
Provide the ability to restore an object to its previous state (undo via
rollback).
The memento pattern is implemented with three objects: the originator, a
caretaker and a memento. The originator is some object that has an
internal state. The caretaker is going to do something to the
originator, but wants to be able to undo the change. The caretaker first
asks the originator for a memento object. Then it does whatever
operation (or sequence of operations) it was going to do. To roll back
to the state before the operations, it returns the memento object to the
originator. The memento object itself is an opaque object (one which the
caretaker cannot, or should not, change). When using this pattern, care
should be taken if the originator may change other objects or resources
- the memento pattern operates on a single object.
Examples
--------
- The seed of a pseudorandom number generator
- The state in a finite state machine
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Momento UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
Memento.php
.. literalinclude:: Memento.php
:language: php
:linenos:
Originator.php
.. literalinclude:: Originator.php
:language: php
:linenos:
Caretaker.php
.. literalinclude:: Caretaker.php
:language: php
:linenos:
Test
----
Tests/MementoTest.php
.. literalinclude:: Tests/MementoTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Behavioral/Memento
.. _`Memento`: http://en.wikipedia.org/wiki/Memento_pattern

View File

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

View File

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

View File

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

View File

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

View File

@@ -9,6 +9,7 @@ communication.
* [Command](Command) [:notebook:](http://en.wikipedia.org/wiki/Command_pattern)
* [Iterator](Iterator) [:notebook:](http://en.wikipedia.org/wiki/Iterator_pattern)
* [Mediator](Mediator) [:notebook:](http://en.wikipedia.org/wiki/Mediator_pattern)
* [Memento](Behavioral/Memento) [:notebook:](http://en.wikipedia.org/wiki/Memento_pattern)
* [NullObject](NullObject) [:notebook:](http://en.wikipedia.org/wiki/Null_Object_pattern)
* [Observer](Observer) [:notebook:](http://en.wikipedia.org/wiki/Observer_pattern)
* [Specification](Specification) [:notebook:](http://en.wikipedia.org/wiki/Specification_pattern)

23
Behavioral/README.rst Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,10 +0,0 @@
# Abstract Factory
## Purpose
To create series of related or dependent objects without specifying their concrete classes.
Usually the created classes all implement the same interface. The client of the abstract factory does not care about how these objects are created, he just knows how they go together.
## UML Diagram
![Alt AbstractFactory UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,94 @@
`Abstract Factory`_
===================
Purpose
-------
To create series of related or dependent objects without specifying
their concrete classes. Usually the created classes all implement the
same interface. The client of the abstract factory does not care about
how these objects are created, he just knows how they go together.
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt AbstractFactory UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
AbstractFactory.php
.. literalinclude:: AbstractFactory.php
:language: php
:linenos:
JsonFactory.php
.. literalinclude:: JsonFactory.php
:language: php
:linenos:
HtmlFactory.php
.. literalinclude:: HtmlFactory.php
:language: php
:linenos:
MediaInterface.php
.. literalinclude:: MediaInterface.php
:language: php
:linenos:
Picture.php
.. literalinclude:: Picture.php
:language: php
:linenos:
Text.php
.. literalinclude:: Text.php
:language: php
:linenos:
Json/Picture.php
.. literalinclude:: Json/Picture.php
:language: php
:linenos:
Json/Text.php
.. literalinclude:: Json/Text.php
:language: php
:linenos:
Html/Picture.php
.. literalinclude:: Html/Picture.php
:language: php
:linenos:
Html/Text.php
.. literalinclude:: Html/Text.php
:language: php
:linenos:
Test
----
Tests/AbstractFactoryTest.php
.. literalinclude:: Tests/AbstractFactoryTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Creational/AbstractFactory
.. _`Abstract Factory`: http://en.wikipedia.org/wiki/Abstract_factory_pattern

View File

@@ -1,10 +0,0 @@
#
# Purpose
# Examples
*

View File

@@ -1,19 +0,0 @@
# Builder
## Purpose
Builder is an interface that build parts of a complex object.
Sometimes, if the builder has a better knowledge of what it builds, this interface could be an abstract class with default methods (aka adapter).
If you have a complex inheritance tree for objects, it is logical to have a complex inheritance tree for builders too.
Note: Builders have often a fluent interface, see the mock builder of PHPUnit for example.
## Examples
* PHPUnit: Mock Builder
## UML Diagram
![Alt Builder UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,105 @@
`Builder`_
==========
Purpose
-------
Builder is an interface that build parts of a complex object.
Sometimes, if the builder has a better knowledge of what it builds, this
interface could be an abstract class with default methods (aka adapter).
If you have a complex inheritance tree for objects, it is logical to
have a complex inheritance tree for builders too.
Note: Builders have often a fluent interface, see the mock builder of
PHPUnit for example.
Examples
--------
- PHPUnit: Mock Builder
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Builder UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
Director.php
.. literalinclude:: Director.php
:language: php
:linenos:
BuilderInterface.php
.. literalinclude:: BuilderInterface.php
:language: php
:linenos:
BikeBuilder.php
.. literalinclude:: BikeBuilder.php
:language: php
:linenos:
CarBuilder.php
.. literalinclude:: CarBuilder.php
:language: php
:linenos:
Parts/Vehicle.php
.. literalinclude:: Parts/Vehicle.php
:language: php
:linenos:
Parts/Bike.php
.. literalinclude:: Parts/Bike.php
:language: php
:linenos:
Parts/Car.php
.. literalinclude:: Parts/Car.php
:language: php
:linenos:
Parts/Engine.php
.. literalinclude:: Parts/Engine.php
:language: php
:linenos:
Parts/Wheel.php
.. literalinclude:: Parts/Wheel.php
:language: php
:linenos:
Parts/Door.php
.. literalinclude:: Parts/Door.php
:language: php
:linenos:
Test
----
Tests/DirectorTest.php
.. literalinclude:: Tests/DirectorTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Creational/Builder
.. _`Builder`: http://en.wikipedia.org/wiki/Builder_pattern

View File

@@ -1,15 +0,0 @@
# Factory Method
## Purpose
The good point over the SimpleFactory is you can subclass it to implement different ways to create objects
For simple case, this abstract class could be just an interface
This pattern is a "real" Design Pattern because it achieves the "Dependency Inversion Principle" a.k.a the "D" in S.O.L.I.D principles.
It means the FactoryMethod class depends on abstractions, not concrete classes. This is the real trick compared to SimpleFactory or StaticFactory.
## UML Diagram
![Alt FactoryMethod UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,83 @@
`Factory Method`_
=================
Purpose
-------
The good point over the SimpleFactory is you can subclass it to
implement different ways to create objects
For simple case, this abstract class could be just an interface
This pattern is a "real" Design Pattern because it achieves the
"Dependency Inversion Principle" a.k.a the "D" in S.O.L.I.D principles.
It means the FactoryMethod class depends on abstractions, not concrete
classes. This is the real trick compared to SimpleFactory or
StaticFactory.
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt FactoryMethod UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
FactoryMethod.php
.. literalinclude:: FactoryMethod.php
:language: php
:linenos:
ItalianFactory.php
.. literalinclude:: ItalianFactory.php
:language: php
:linenos:
GermanFactory.php
.. literalinclude:: GermanFactory.php
:language: php
:linenos:
VehicleInterface.php
.. literalinclude:: VehicleInterface.php
:language: php
:linenos:
Porsche.php
.. literalinclude:: Porsche.php
:language: php
:linenos:
Bicycle.php
.. literalinclude:: Bicycle.php
:language: php
:linenos:
Ferrari.php
.. literalinclude:: Ferrari.php
:language: php
:linenos:
Test
----
Tests/FactoryMethodTest.php
.. literalinclude:: Tests/FactoryMethodTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Creational/FactoryMethod
.. _`Factory Method`: http://en.wikipedia.org/wiki/Factory_method_pattern

View File

@@ -1,16 +0,0 @@
# Multiton
**THIS IS CONSIDERED TO BE AN ANTI-PATTERN! FOR BETTER TESTABILITY AND MAINTAINABILITY USE DEPENDENCY INJECTION!**
# Purpose
To have only a list of named instances that are used, like a singleton but with n instances.
# Examples
* 2 DB Connectors, e.g. one for MySQL, the other for SQLite
* multiple Loggers (one for debug messages, one for errors)
## UML Diagram
![Alt Multiton UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,40 @@
Multiton
========
**THIS IS CONSIDERED TO BE AN ANTI-PATTERN! FOR BETTER TESTABILITY AND
MAINTAINABILITY USE DEPENDENCY INJECTION!**
Purpose
-------
To have only a list of named instances that are used, like a singleton
but with n instances.
Examples
--------
- 2 DB Connectors, e.g. one for MySQL, the other for SQLite
- multiple Loggers (one for debug messages, one for errors)
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Multiton UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
Multiton.php
.. literalinclude:: Multiton.php
:language: php
:linenos:
Test
----
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Creational/Multiton

View File

@@ -1,12 +0,0 @@
Pool
====
The **object pool pattern** is a software creational design pattern that uses a set of initialized objects kept ready to use a "pool" rather than allocating and destroying them on demand. A client of the pool will request an object from the pool and perform operations on the returned object. When the client has finished, it returns the object, which is a specific type of factory object, to the pool rather than destroying it.
Object pooling can offer a significant performance boost in situations where the cost of initializing a class instance is high, the rate of instantiation of a class is high, and the number of instances in use at any one time is low. The pooled object is obtained in predictable time when creation of the new objects (especially over network) may take variable time.
However these benefits are mostly true for objects that are expensive with respect to time, such as database connections, socket connections, threads and large graphic objects like fonts or bitmaps. In certain situations, simple object pooling (that hold no external resources, but only occupy memory) may not be efficient and could decrease performance.
## UML Diagram
![Alt Pool UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,70 @@
`Pool`_
=======
The **object pool pattern** is a software creational design pattern that
uses a set of initialized objects kept ready to use a "pool" rather
than allocating and destroying them on demand. A client of the pool will
request an object from the pool and perform operations on the returned
object. When the client has finished, it returns the object, which is a
specific type of factory object, to the pool rather than destroying it.
Object pooling can offer a significant performance boost in situations
where the cost of initializing a class instance is high, the rate of
instantiation of a class is high, and the number of instances in use at
any one time is low. The pooled object is obtained in predictable time
when creation of the new objects (especially over network) may take
variable time.
However these benefits are mostly true for objects that are expensive
with respect to time, such as database connections, socket connections,
threads and large graphic objects like fonts or bitmaps. In certain
situations, simple object pooling (that hold no external resources, but
only occupy memory) may not be efficient and could decrease performance.
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Pool UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
Pool.php
.. literalinclude:: Pool.php
:language: php
:linenos:
Processor.php
.. literalinclude:: Processor.php
:language: php
:linenos:
Worker.php
.. literalinclude:: Worker.php
:language: php
:linenos:
Test
----
Tests/PoolTest.php
.. literalinclude:: Tests/PoolTest.php
:language: php
:linenos:
Tests/TestWorker.php
.. literalinclude:: Tests/TestWorker.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Creational/Pool
.. _`Pool`: http://en.wikipedia.org/wiki/Object_pool_pattern

View File

@@ -1,13 +0,0 @@
# Prototype
## Purpose
To avoid the cost of creating objects the standard way (new Foo()) and instead create a prototype and clone it.
## Examples
* Large amounts of data (e.g. create 1,000,000 rows in a database at once via a ORM).
## UML Diagram
![Alt Prototype UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,56 @@
`Prototype`_
============
Purpose
-------
To avoid the cost of creating objects the standard way (new Foo()) and
instead create a prototype and clone it.
Examples
--------
- Large amounts of data (e.g. create 1,000,000 rows in a database at
once via a ORM).
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Prototype UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
index.php
.. literalinclude:: index.php
:language: php
:linenos:
BookPrototype.php
.. literalinclude:: BookPrototype.php
:language: php
:linenos:
BarBookPrototype.php
.. literalinclude:: BarBookPrototype.php
:language: php
:linenos:
FooBookPrototype.php
.. literalinclude:: FooBookPrototype.php
:language: php
:linenos:
Test
----
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Creational/Prototype
.. _`Prototype`: http://en.wikipedia.org/wiki/Prototype_pattern

22
Creational/README.rst Normal file
View File

@@ -0,0 +1,22 @@
Creational
==========
In software engineering, creational design patterns are design patterns
that deal with object creation mechanisms, trying to create objects in a
manner suitable to the situation. The basic form of object creation
could result in design problems or added complexity to the design.
Creational design patterns solve this problem by somehow controlling
this object creation.
.. toctree::
:titlesonly:
AbstractFactory/README
Builder/README
FactoryMethod/README
Multiton/README
Pool/README
Prototype/README
SimpleFactory/README
Singleton/README
StaticFactory/README

View File

@@ -1,13 +0,0 @@
# Simple Factory
## Purpose
ConcreteFactory is a simple factory pattern.
It differs from the static factory because it is NOT static and as you know: static => global => evil!
Therefore, you can have multiple factories, differently parametrized, you can subclass it and you can mock-up it.
## UML Diagram
![Alt SimpleFactory UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,60 @@
Simple Factory
==============
Purpose
-------
ConcreteFactory is a simple factory pattern.
It differs from the static factory because it is NOT static and as you
know: static => global => evil!
Therefore, you can have multiple factories, differently parametrized,
you can subclass it and you can mock-up it.
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt SimpleFactory UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
ConcreteFactory.php
.. literalinclude:: ConcreteFactory.php
:language: php
:linenos:
VehicleInterface.php
.. literalinclude:: VehicleInterface.php
:language: php
:linenos:
Bicycle.php
.. literalinclude:: Bicycle.php
:language: php
:linenos:
Scooter.php
.. literalinclude:: Scooter.php
:language: php
:linenos:
Test
----
Tests/SimpleFactoryTest.php
.. literalinclude:: Tests/SimpleFactoryTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Creational/SimpleFactory

View File

@@ -1,17 +0,0 @@
# Singleton
**THIS IS CONSIDERED TO BE AN ANTI-PATTERN! FOR BETTER TESTABILITY AND MAINTAINABILITY USE DEPENDENCY INJECTION!**
## Purpose
To have only one instance of this object in the application that will handle all calls.
## Examples
* DB Connector
* Logger (may also be a Multiton if there are many log files for several purposes)
* Lock file for the application (there is only one in the filesystem ...)
## UML Diagram
![Alt Singleton UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,50 @@
`Singleton`_
============
**THIS IS CONSIDERED TO BE AN ANTI-PATTERN! FOR BETTER TESTABILITY AND
MAINTAINABILITY USE DEPENDENCY INJECTION!**
Purpose
-------
To have only one instance of this object in the application that will
handle all calls.
Examples
--------
- DB Connector
- Logger (may also be a Multiton if there are many log files for
several purposes)
- Lock file for the application (there is only one in the filesystem
...)
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Singleton UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
Singleton.php
.. literalinclude:: Singleton.php
:language: php
:linenos:
Test
----
Tests/SingletonTest.php
.. literalinclude:: Tests/SingletonTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Creational/Singleton
.. _`Singleton`: http://en.wikipedia.org/wiki/Singleton_pattern

View File

@@ -1,15 +0,0 @@
# Static Factory
## Purpose
Similar to the AbstractFactory, this pattern is used to create series of related or dependent objects.
The difference between this and the abstract factory pattern is that the static factory pattern uses just one static
method to create all types of objects it can create. It is usually named `factory` or `build`.
## Examples
* Zend Framework: `Zend_Cache_Backend` or `_Frontend` use a factory method create cache backends or frontends
## UML Diagram
![Alt StaticFactory UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,64 @@
Static Factory
==============
Purpose
-------
Similar to the AbstractFactory, this pattern is used to create series of
related or dependent objects. The difference between this and the
abstract factory pattern is that the static factory pattern uses just
one static method to create all types of objects it can create. It is
usually named ``factory`` or ``build``.
Examples
--------
- Zend Framework: ``Zend_Cache_Backend`` or ``_Frontend`` use a factory
method create cache backends or frontends
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt StaticFactory UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
StaticFactory.php
.. literalinclude:: StaticFactory.php
:language: php
:linenos:
FormatterInterface.php
.. literalinclude:: FormatterInterface.php
:language: php
:linenos:
FormatString.php
.. literalinclude:: FormatString.php
:language: php
:linenos:
FormatNumber.php
.. literalinclude:: FormatNumber.php
:language: php
:linenos:
Test
----
Tests/StaticFactoryTest.php
.. literalinclude:: Tests/StaticFactoryTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Creational/StaticFactory

192
Makefile Normal file
View File

@@ -0,0 +1,192 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " applehelp to make an Apple Help Book"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " xml to make Docutils-native XML files"
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo " coverage to run coverage check of the documentation (if enabled)"
clean:
rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/DesignPatternsPHP.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/DesignPatternsPHP.qhc"
applehelp:
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
@echo
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
@echo "N.B. You won't be able to view it unless you put it in" \
"~/Library/Documentation/Help or install it in your application" \
"bundle."
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/DesignPatternsPHP"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/DesignPatternsPHP"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
coverage:
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
@echo "Testing of coverage in the sources finished, look at the " \
"results in $(BUILDDIR)/coverage/python.txt."
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."

View File

@@ -1,13 +0,0 @@
# Delegation
## Purpose
...
## Examples
...
## UML Diagram
![Alt Delegation UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,54 @@
`Delegation`_
=============
Purpose
-------
...
Examples
--------
...
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Delegation UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
Usage.php
.. literalinclude:: Usage.php
:language: php
:linenos:
TeamLead.php
.. literalinclude:: TeamLead.php
:language: php
:linenos:
JuniorDeveloper.php
.. literalinclude:: JuniorDeveloper.php
:language: php
:linenos:
Test
----
Tests/DelegationTest.php
.. literalinclude:: Tests/DelegationTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/More/Delegation
.. _`Delegation`: http://en.wikipedia.org/wiki/Delegation_pattern

9
More/README.rst Normal file
View File

@@ -0,0 +1,9 @@
More
====
.. toctree::
:titlesonly:
Delegation/README
ServiceLocator/README
Repository/README

View File

@@ -1,16 +0,0 @@
# Repository
## Purpose
Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.
Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer.
Repository also supports the objective of achieving a clean separation and one-way dependency between the domain and data mapping layers.
## Examples
* Doctrine 2 ORM: there is Repository that mediates between Entity and DBAL and contains methods to retrieve objects
* Laravel Framework
## UML Diagram
![Alt Repository UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,61 @@
Repository
==========
Purpose
-------
Mediates between the domain and data mapping layers using a
collection-like interface for accessing domain objects. Repository
encapsulates the set of objects persisted in a data store and the
operations performed over them, providing a more object-oriented view of
the persistence layer. Repository also supports the objective of
achieving a clean separation and one-way dependency between the domain
and data mapping layers.
Examples
--------
- Doctrine 2 ORM: there is Repository that mediates between Entity and
DBAL and contains methods to retrieve objects
- Laravel Framework
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt Repository UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
Post.php
.. literalinclude:: Post.php
:language: php
:linenos:
PostRepository.php
.. literalinclude:: PostRepository.php
:language: php
:linenos:
Storage.php
.. literalinclude:: Storage.php
:language: php
:linenos:
MemoryStorage.php
.. literalinclude:: MemoryStorage.php
:language: php
:linenos:
Test
----
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/More/Repository

View File

@@ -1,20 +0,0 @@
# Service Locator
## Purpose
To implement a loosely coupled architecture in order to get better testable, maintainable and extendable code.
DI pattern and Service Locator pattern are an implementation of the Inverse of Control pattern.
## Usage
With `ServiceLocator` you can register a service for a given interface. By using the interface you can retrieve the service
and use it in the classes of the application without knowing its implementation. You can configure and inject the
Service Locator object on bootstrap.
## Examples
* Zend Framework 2 uses Service Locator to create and share services used in the framework(i.e. EventManager, ModuleManager, all custom user services provided by modules, etc...)
## UML Diagram
![Alt ServiceLocator UML Diagram](uml/uml.png)

View File

@@ -0,0 +1,84 @@
`Service Locator`_
==================
Purpose
-------
To implement a loosely coupled architecture in order to get better
testable, maintainable and extendable code. DI pattern and Service
Locator pattern are an implementation of the Inverse of Control pattern.
Usage
-----
With ``ServiceLocator`` you can register a service for a given
interface. By using the interface you can retrieve the service and use
it in the classes of the application without knowing its implementation.
You can configure and inject the Service Locator object on bootstrap.
Examples
--------
- Zend Framework 2 uses Service Locator to create and share services
used in the framework(i.e. EventManager, ModuleManager, all custom
user services provided by modules, etc...)
UML Diagram
-----------
.. image:: uml/uml.png
:alt: Alt ServiceLocator UML Diagram
:align: center
Code
----
You can also find these code on `GitHub`_
ServiceLocatorInterface.php
.. literalinclude:: ServiceLocatorInterface.php
:language: php
:linenos:
ServiceLocator.php
.. literalinclude:: ServiceLocator.php
:language: php
:linenos:
LogServiceInterface.php
.. literalinclude:: LogServiceInterface.php
:language: php
:linenos:
LogService.php
.. literalinclude:: LogService.php
:language: php
:linenos:
DatabaseServiceInterface.php
.. literalinclude:: DatabaseServiceInterface.php
:language: php
:linenos:
DatabaseService.php
.. literalinclude:: DatabaseService.php
:language: php
:linenos:
Test
----
Tests/ServiceLocatorTest.php
.. literalinclude:: Tests/ServiceLocatorTest.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/More/ServiceLocator
.. _`Service Locator`: http://en.wikipedia.org/wiki/Service_locator_pattern

View File

@@ -2,6 +2,9 @@
[![Build Status](https://travis-ci.org/domnikl/DesignPatternsPHP.png?branch=master)](https://travis-ci.org/domnikl/DesignPatternsPHP)
[Read the Docs of DesignPatternsPHP](http://designpatternsphp.readthedocs.org)
or [Download as PDF/Epub](https://readthedocs.org/projects/designpatternsphp/downloads/)
This is a collection of known design patterns and some sample code how to implement them in PHP. Every pattern has a small list of examples (most of them from Zend Framework, Symfony2 or Doctrine2 as I'm most familiar with this software).
I think the problem with patterns is that often people do know them but don't know when to apply which.

73
README.rst Normal file
View File

@@ -0,0 +1,73 @@
.. DesignPatternsPHP
=================
DesignPatternsPHP
=================
.. image:: https://readthedocs.org/projects/designpatternsphp/badge/?version=latest
:target: https://readthedocs.org/projects/designpatternsphp/?badge=latest
:alt: Documentation Status
This is a collection of known `design patterns`_ and some sample code how
to implement them in PHP. Every pattern has a small list of examples
(most of them from Zend Framework, Symfony2 or Doctrine2 as I'm most
familiar with this software).
I think the problem with patterns is that often people do know them but
don't know when to apply which.
Patterns
--------
The patterns can be structured in roughly three different categories.
Please click on **the title of every pattern's page** for a full explanation of the pattern on Wikipedia.
.. toctree::
:titlesonly:
:numbered:
Creational/README
Structural/README
Behavioral/README
More/README
Contribute
----------
Please feel free to fork and extend existing or add your own examples
and send a pull request with your changes! To establish a consistent
code quality, please check your code using
`PHP CodeSniffer`_ against `PSR2 standard`_
using ``./vendor/bin/phpcs -p --standard=PSR2 --ignore=vendor .``.
License
-------
(The MIT License)
Copyright (c) 2014 `Dominik Liebler`_ and `contributors`_
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
.. _`design patterns`: http://en.wikipedia.org/wiki/Software_design_pattern
.. _`PHP CodeSniffer`: https://github.com/squizlabs/PHP_CodeSniffer
.. _`PSR2 standard`: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md
.. _`Dominik Liebler`: https://github.com/domnikl
.. _`contributors`: https://github.com/domnikl/DesignPatternsPHP/graphs/contributors

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
.. _`Adapter / Wrapper`: http://en.wikipedia.org/wiki/Adapter_pattern

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. (http://en.wikipedia.org/wiki/Bridge\_pattern)
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
.. _`Bridge`: http://en.wikipedia.org/wiki/Bridge_pattern

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
.. _`Composite`: http://en.wikipedia.org/wiki/Composite_pattern

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
.. _`Data Mapper`: http://en.wikipedia.org/wiki/Data_mapper_pattern

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
.. _`Decorator`: http://en.wikipedia.org/wiki/Decorator_pattern

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
.. _`Dependency Injection`: http://en.wikipedia.org/wiki/Dependency_injection

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
.. _`Facade`: http://en.wikipedia.org/wiki/Facade_pattern

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,47 @@
`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
.. _`Fluent Interface`: http://en.wikipedia.org/wiki/Fluent_interface

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
.. _`Proxy`: http://en.wikipedia.org/wiki/Proxy_pattern

20
Structural/README.rst Normal file
View File

@@ -0,0 +1,20 @@
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

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: ``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
.. _`Registry`: http://en.wikipedia.org/wiki/Service_locator_pattern

284
conf.py Normal file
View File

@@ -0,0 +1,284 @@
# -*- coding: utf-8 -*-
#
# DesignPatternsPHP documentation build configuration file, created by
# sphinx-quickstart on Thu Apr 2 00:05:03 2015.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys
import os
import shlex
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = []
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'README'
# General information about the project.
project = u'DesignPatternsPHP'
copyright = u'2015, Dominik Liebler and contributors'
author = u'Dominik Liebler and contributors'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '1.0'
# The full version, including alpha/beta/rc tags.
release = '1.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all
# documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'sphinx_rtd_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
#html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# Now only 'ja' uses this config value
#html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
#html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
htmlhelp_basename = 'DesignPatternsPHPdoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
'preamble': '\setcounter{tocdepth}{2}',
# Latex figure (float) alignment
#'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'DesignPatternsPHP.tex', u'DesignPatternsPHP Documentation',
u'Dominik Liebler and contributors', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'designpatternsphp', u'DesignPatternsPHP Documentation',
[author], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'DesignPatternsPHP', u'DesignPatternsPHP Documentation',
author, 'DesignPatternsPHP', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False

263
make.bat Normal file
View File

@@ -0,0 +1,263 @@
@ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
set I18NSPHINXOPTS=%SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. texinfo to make Texinfo files
echo. gettext to make PO message catalogs
echo. changes to make an overview over all changed/added/deprecated items
echo. xml to make Docutils-native XML files
echo. pseudoxml to make pseudoxml-XML files for display purposes
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
echo. coverage to run coverage check of the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
REM Check if sphinx-build is available and fallback to Python version if any
%SPHINXBUILD% 2> nul
if errorlevel 9009 goto sphinx_python
goto sphinx_ok
:sphinx_python
set SPHINXBUILD=python -m sphinx.__init__
%SPHINXBUILD% 2> nul
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
:sphinx_ok
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\DesignPatternsPHP.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\DesignPatternsPHP.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdf" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf
cd %~dp0
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdfja" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf-ja
cd %~dp0
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)
if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
if "%1" == "coverage" (
%SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
if errorlevel 1 exit /b 1
echo.
echo.Testing of coverage in the sources finished, look at the ^
results in %BUILDDIR%/coverage/python.txt.
goto end
)
if "%1" == "xml" (
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The XML files are in %BUILDDIR%/xml.
goto end
)
if "%1" == "pseudoxml" (
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
goto end
)
:end