mirror of
https://github.com/DesignPatternsPHP/DesignPatternsPHP.git
synced 2025-08-05 14:37:27 +02:00
Merge branch 'feature/coding-standards'
This commit is contained in:
@@ -28,6 +28,7 @@ abstract class AbstractFactory
|
|||||||
* Creates a text component
|
* Creates a text component
|
||||||
*
|
*
|
||||||
* @param string $content
|
* @param string $content
|
||||||
|
*
|
||||||
* @return Text
|
* @return Text
|
||||||
*/
|
*/
|
||||||
abstract public function createText($content);
|
abstract public function createText($content);
|
||||||
@@ -37,6 +38,7 @@ abstract class AbstractFactory
|
|||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
* @param string $name
|
* @param string $name
|
||||||
|
*
|
||||||
* @return Picture
|
* @return Picture
|
||||||
*/
|
*/
|
||||||
abstract public function createPicture($path, $name = '');
|
abstract public function createPicture($path, $name = '');
|
||||||
|
@@ -11,7 +11,6 @@ use DesignPatterns\AbstractFactory\Picture as BasePicture;
|
|||||||
*/
|
*/
|
||||||
class Picture extends BasePicture
|
class Picture extends BasePicture
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* some crude rendering from HTML output
|
* some crude rendering from HTML output
|
||||||
*
|
*
|
||||||
@@ -19,7 +18,6 @@ class Picture extends BasePicture
|
|||||||
*/
|
*/
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
return sprintf('<img src="%s" title="$s"/>', $this->_path, $this->_name);
|
return sprintf('<img src="%s" title="$s"/>', $this->path, $this->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,6 @@ use DesignPatterns\AbstractFactory\Text as BaseText;
|
|||||||
*/
|
*/
|
||||||
class Text extends BaseText
|
class Text extends BaseText
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* some crude rendering from HTML output
|
* some crude rendering from HTML output
|
||||||
*
|
*
|
||||||
@@ -19,7 +18,6 @@ class Text extends BaseText
|
|||||||
*/
|
*/
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
return '<div>' . htmlspecialchars($this->_text) . '</div>';
|
return '<div>' . htmlspecialchars($this->text) . '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -9,12 +9,12 @@ namespace DesignPatterns\AbstractFactory;
|
|||||||
*/
|
*/
|
||||||
class HtmlFactory extends AbstractFactory
|
class HtmlFactory extends AbstractFactory
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a picture component
|
* Creates a picture component
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
* @param string $name
|
* @param string $name
|
||||||
|
*
|
||||||
* @return Html\Picture|Picture
|
* @return Html\Picture|Picture
|
||||||
*/
|
*/
|
||||||
public function createPicture($path, $name = '')
|
public function createPicture($path, $name = '')
|
||||||
@@ -26,11 +26,11 @@ class HtmlFactory extends AbstractFactory
|
|||||||
* Creates a text component
|
* Creates a text component
|
||||||
*
|
*
|
||||||
* @param string $content
|
* @param string $content
|
||||||
|
*
|
||||||
* @return Html\Text|Text
|
* @return Html\Text|Text
|
||||||
*/
|
*/
|
||||||
public function createText($content)
|
public function createText($content)
|
||||||
{
|
{
|
||||||
return new Html\Text($content);
|
return new Html\Text($content);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,6 @@ use DesignPatterns\AbstractFactory\Picture as BasePicture;
|
|||||||
*/
|
*/
|
||||||
class Picture extends BasePicture
|
class Picture extends BasePicture
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* some crude rendering from JSON output
|
* some crude rendering from JSON output
|
||||||
*
|
*
|
||||||
@@ -19,7 +18,6 @@ class Picture extends BasePicture
|
|||||||
*/
|
*/
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
return json_encode(array('title' => $this->_name, 'path' => $this->_path));
|
return json_encode(array('title' => $this->name, 'path' => $this->path));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,6 @@ use DesignPatterns\AbstractFactory\Text as BaseText;
|
|||||||
*/
|
*/
|
||||||
class Text extends BaseText
|
class Text extends BaseText
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* some crude rendering from JSON output
|
* some crude rendering from JSON output
|
||||||
*
|
*
|
||||||
@@ -19,7 +18,6 @@ class Text extends BaseText
|
|||||||
*/
|
*/
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
return json_encode(array('content' => $this->_text));
|
return json_encode(array('content' => $this->text));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -16,6 +16,7 @@ class JsonFactory extends AbstractFactory
|
|||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
* @param string $name
|
* @param string $name
|
||||||
|
*
|
||||||
* @return Json\Picture|Picture
|
* @return Json\Picture|Picture
|
||||||
*/
|
*/
|
||||||
public function createPicture($path, $name = '')
|
public function createPicture($path, $name = '')
|
||||||
@@ -23,16 +24,15 @@ class JsonFactory extends AbstractFactory
|
|||||||
return new Json\Picture($path, $name);
|
return new Json\Picture($path, $name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a text component
|
* Creates a text component
|
||||||
*
|
*
|
||||||
* @param string $content
|
* @param string $content
|
||||||
|
*
|
||||||
* @return Json\Text|Text
|
* @return Json\Text|Text
|
||||||
*/
|
*/
|
||||||
public function createText($content)
|
public function createText($content)
|
||||||
{
|
{
|
||||||
return new Json\Text($content);
|
return new Json\Text($content);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -3,12 +3,12 @@
|
|||||||
namespace DesignPatterns\AbstractFactory;
|
namespace DesignPatterns\AbstractFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface Media
|
* Interface MediaInterface
|
||||||
*
|
*
|
||||||
* This contract is not part of the pattern, in general case, each component
|
* This contract is not part of the pattern, in general case, each component
|
||||||
* are not related
|
* are not related
|
||||||
*/
|
*/
|
||||||
interface Media
|
interface MediaInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -16,5 +16,5 @@ interface Media
|
|||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function render();
|
public function render();
|
||||||
}
|
}
|
@@ -5,7 +5,7 @@ namespace DesignPatterns\AbstractFactory;
|
|||||||
/**
|
/**
|
||||||
* Class Picture
|
* Class Picture
|
||||||
*/
|
*/
|
||||||
abstract class Picture implements Media
|
abstract class Picture implements MediaInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -5,7 +5,7 @@ namespace DesignPatterns\AbstractFactory;
|
|||||||
/**
|
/**
|
||||||
* Class Text
|
* Class Text
|
||||||
*/
|
*/
|
||||||
abstract class Text implements Media
|
abstract class Text implements MediaInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Adapter;
|
namespace DesignPatterns\Adapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,15 +7,19 @@ namespace DesignPatterns\Adapter;
|
|||||||
*/
|
*/
|
||||||
class Book implements PaperBookInterface
|
class Book implements PaperBookInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function open()
|
public function open()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function turnPage()
|
public function turnPage()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@@ -1,26 +1,26 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Adapter;
|
namespace DesignPatterns\Adapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ElecBookAdapter is an adapter to fit an e-book like a paper book
|
* EBookAdapter is an adapter to fit an e-book like a paper book
|
||||||
*
|
*
|
||||||
* This is the adapter here. Notice it implemennts PaperBookInterface,
|
* This is the adapter here. Notice it implemennts PaperBookInterface,
|
||||||
* therefore you don't have to change the code of the client which using paper book.
|
* therefore you don't have to change the code of the client which using paper book.
|
||||||
*/
|
*/
|
||||||
class ElecBookAdapter implements PaperBookInterface
|
class EBookAdapter implements PaperBookInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var EBookInterface
|
||||||
|
*/
|
||||||
protected $eBook;
|
protected $eBook;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notice the constructor, it "wraps" an electronic book
|
* Notice the constructor, it "wraps" an electronic book
|
||||||
|
*
|
||||||
|
* @param EBookInterface $ebook
|
||||||
*/
|
*/
|
||||||
public function __construct(ElecBookInterface $ebook)
|
public function __construct(EBookInterface $ebook)
|
||||||
{
|
{
|
||||||
$this->eBook = $ebook;
|
$this->eBook = $ebook;
|
||||||
}
|
}
|
||||||
@@ -33,9 +33,11 @@ class ElecBookAdapter implements PaperBookInterface
|
|||||||
$this->eBook->pressStart();
|
$this->eBook->pressStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* turns pages
|
||||||
|
*/
|
||||||
public function turnPage()
|
public function turnPage()
|
||||||
{
|
{
|
||||||
$this->eBook->pressNext();
|
$this->eBook->pressNext();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
23
Adapter/EBookInterface.php
Normal file
23
Adapter/EBookInterface.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Adapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EBookInterface is a contract for an electronic book
|
||||||
|
*/
|
||||||
|
interface EBookInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* go to next page
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function pressNext();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* start the book
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function pressStart();
|
||||||
|
}
|
@@ -1,18 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Adapter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ElecBookInterface is a contract for an electronic book
|
|
||||||
*/
|
|
||||||
interface ElecBookInterface
|
|
||||||
{
|
|
||||||
|
|
||||||
function pressNext();
|
|
||||||
|
|
||||||
function pressStart();
|
|
||||||
}
|
|
@@ -1,27 +1,25 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Adapter;
|
namespace DesignPatterns\Adapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kindle is a concrete electronic book
|
* Kindle is a concrete electronic book
|
||||||
*
|
|
||||||
* @author flo
|
|
||||||
*/
|
*/
|
||||||
class Kindle implements ElecBookInterface
|
class Kindle implements EBookInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function pressNext()
|
public function pressNext()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function pressStart()
|
public function pressStart()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Adapter;
|
namespace DesignPatterns\Adapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,8 +7,17 @@ namespace DesignPatterns\Adapter;
|
|||||||
*/
|
*/
|
||||||
interface PaperBookInterface
|
interface PaperBookInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* method to turn pages
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function turnPage();
|
||||||
|
|
||||||
function turnPage();
|
/**
|
||||||
|
* method to open the book
|
||||||
function open();
|
*
|
||||||
}
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function open();
|
||||||
|
}
|
||||||
|
@@ -1,43 +1,55 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Builder;
|
namespace DesignPatterns\Builder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BikeBuilder builds bike
|
* BikeBuilder builds bike
|
||||||
*/
|
*/
|
||||||
class BikeBuilder implements Builder
|
class BikeBuilder implements BuilderInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var Parts\Bike
|
||||||
|
*/
|
||||||
protected $bike;
|
protected $bike;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function addDoors()
|
public function addDoors()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function addEngine()
|
public function addEngine()
|
||||||
{
|
{
|
||||||
$this->bike->setPart('engine', new Parts\Engine());
|
$this->bike->setPart('engine', new Parts\Engine());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function addWheel()
|
public function addWheel()
|
||||||
{
|
{
|
||||||
$this->bike->setPart('forwardWheel', new Parts\Wheel());
|
$this->bike->setPart('forwardWheel', new Parts\Wheel());
|
||||||
$this->bike->setPart('rearWheel', new Parts\Wheel());
|
$this->bike->setPart('rearWheel', new Parts\Wheel());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function createVehicle()
|
public function createVehicle()
|
||||||
{
|
{
|
||||||
$this->bike = new Parts\Bike();
|
$this->bike = new Parts\Bike();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function getVehicle()
|
public function getVehicle()
|
||||||
{
|
{
|
||||||
return $this->bike;
|
return $this->bike;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Builder;
|
namespace DesignPatterns\Builder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,16 +14,30 @@ namespace DesignPatterns\Builder;
|
|||||||
* Note: Builders have often a fluent interface, see the mock builder of
|
* Note: Builders have often a fluent interface, see the mock builder of
|
||||||
* PHPUnit for example.
|
* PHPUnit for example.
|
||||||
*/
|
*/
|
||||||
interface Builder
|
interface BuilderInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function createVehicle();
|
||||||
|
|
||||||
function createVehicle();
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function addWheel();
|
||||||
|
|
||||||
function addWheel();
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function addEngine();
|
||||||
|
|
||||||
function addEngine();
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function addDoors();
|
||||||
|
|
||||||
function addDoors();
|
/**
|
||||||
|
* @return mixed
|
||||||
function getVehicle();
|
*/
|
||||||
}
|
public function getVehicle();
|
||||||
|
}
|
@@ -1,30 +1,37 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Builder;
|
namespace DesignPatterns\Builder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CarBuilder builds car
|
* CarBuilder builds car
|
||||||
*/
|
*/
|
||||||
class CarBuilder implements Builder
|
class CarBuilder implements BuilderInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var Parts\Car
|
||||||
|
*/
|
||||||
protected $car;
|
protected $car;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function addDoors()
|
public function addDoors()
|
||||||
{
|
{
|
||||||
$this->car->setPart('rightdoor', new Parts\Door());
|
$this->car->setPart('rightdoor', new Parts\Door());
|
||||||
$this->car->setPart('leftDoor', new Parts\Door());
|
$this->car->setPart('leftDoor', new Parts\Door());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function addEngine()
|
public function addEngine()
|
||||||
{
|
{
|
||||||
$this->car->setPart('engine', new Parts\Engine());
|
$this->car->setPart('engine', new Parts\Engine());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function addWheel()
|
public function addWheel()
|
||||||
{
|
{
|
||||||
$this->car->setPart('wheelLF', new Parts\Wheel());
|
$this->car->setPart('wheelLF', new Parts\Wheel());
|
||||||
@@ -33,14 +40,19 @@ class CarBuilder implements Builder
|
|||||||
$this->car->setPart('wheelRR', new Parts\Wheel());
|
$this->car->setPart('wheelRR', new Parts\Wheel());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function createVehicle()
|
public function createVehicle()
|
||||||
{
|
{
|
||||||
$this->car = new Parts\Car();
|
$this->car = new Parts\Car();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Parts\Car
|
||||||
|
*/
|
||||||
public function getVehicle()
|
public function getVehicle()
|
||||||
{
|
{
|
||||||
return $this->car;
|
return $this->car;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Builder;
|
namespace DesignPatterns\Builder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,8 +14,12 @@ class Director
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The director don't know 'bout concrete part
|
* The director don't know 'bout concrete part
|
||||||
|
*
|
||||||
|
* @param BuilderInterface $builder
|
||||||
|
*
|
||||||
|
* @return Parts\Vehicle
|
||||||
*/
|
*/
|
||||||
public function build(Builder $builder)
|
public function build(BuilderInterface $builder)
|
||||||
{
|
{
|
||||||
$builder->createVehicle();
|
$builder->createVehicle();
|
||||||
$builder->addDoors();
|
$builder->addDoors();
|
||||||
@@ -28,5 +28,4 @@ class Director
|
|||||||
|
|
||||||
return $builder->getVehicle();
|
return $builder->getVehicle();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Builder\Parts;
|
namespace DesignPatterns\Builder\Parts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,5 +7,5 @@ namespace DesignPatterns\Builder\Parts;
|
|||||||
*/
|
*/
|
||||||
class Bike extends Vehicle
|
class Bike extends Vehicle
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Builder\Parts;
|
namespace DesignPatterns\Builder\Parts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,5 +7,5 @@ namespace DesignPatterns\Builder\Parts;
|
|||||||
*/
|
*/
|
||||||
class Car extends Vehicle
|
class Car extends Vehicle
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,10 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Builder\Parts;
|
namespace DesignPatterns\Builder\Parts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Door
|
||||||
|
*/
|
||||||
class Door
|
class Door
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,10 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Builder\Parts;
|
namespace DesignPatterns\Builder\Parts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Engine
|
||||||
|
*/
|
||||||
class Engine
|
class Engine
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,22 +1,23 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Builder\Parts;
|
namespace DesignPatterns\Builder\Parts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vehicle is a contract for a vehicle
|
* VehicleInterface is a contract for a vehicle
|
||||||
*/
|
*/
|
||||||
abstract class Vehicle
|
abstract class Vehicle
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
protected $data;
|
protected $data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $key
|
||||||
|
* @param mixed $value
|
||||||
|
*/
|
||||||
public function setPart($key, $value)
|
public function setPart($key, $value)
|
||||||
{
|
{
|
||||||
$this->data[$key] = $value;
|
$this->data[$key] = $value;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -2,7 +2,10 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Builder\Parts;
|
namespace DesignPatterns\Builder\Parts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Wheel
|
||||||
|
*/
|
||||||
class Wheel
|
class Wheel
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,96 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace DesignPatterns;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* chain of responsibilities pattern
|
|
||||||
*
|
|
||||||
* Purpose:
|
|
||||||
* to build a chain of objects to handle a call. if one object cannot handle a call, it delegates the call to the next
|
|
||||||
* in the chain and so forth
|
|
||||||
*
|
|
||||||
* Examples:
|
|
||||||
* - logging framework
|
|
||||||
* - 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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
// the idea is good but in general, the Handler component in this pattern
|
|
||||||
// is an abstract class which makes much more of the work
|
|
||||||
interface KeyValueStorage
|
|
||||||
{
|
|
||||||
public function get($key);
|
|
||||||
}
|
|
||||||
|
|
||||||
class SlowStorage implements KeyValueStorage
|
|
||||||
{
|
|
||||||
protected $_data = array();
|
|
||||||
|
|
||||||
public function __construct($data = array())
|
|
||||||
{
|
|
||||||
$this->_data = $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* this class has no next handler, so it MUST be able to handle all requests
|
|
||||||
*
|
|
||||||
* @param $key
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function get($key)
|
|
||||||
{
|
|
||||||
return $this->_data[$key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class FastStorage implements KeyValueStorage
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
protected $_data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the next handler in the chain
|
|
||||||
*
|
|
||||||
* @var \DesignPatterns\KeyValueStorage
|
|
||||||
*/
|
|
||||||
protected $_nextHandler;
|
|
||||||
|
|
||||||
public function __construct(array $data, KeyValueStorage $nextHandler)
|
|
||||||
{
|
|
||||||
$this->_data = $data;
|
|
||||||
$this->_nextHandler = $nextHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* when this storage gets a "miss", search in next handler
|
|
||||||
*
|
|
||||||
* @param $key
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function get($key)
|
|
||||||
{
|
|
||||||
if (true /* miss */) {
|
|
||||||
// delegate the call to the next handler in the chain
|
|
||||||
return $this->_nextHandler->get($key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// BUILD THE STORAGES AND CHAIN
|
|
||||||
|
|
||||||
$slowStorage = new SlowStorage(array('foo' => 'bar'));
|
|
||||||
$fastStorage = new FastStorage(array('bar' => 'baz'), $slowStorage);
|
|
||||||
|
|
||||||
$fastStorage->get('foo'); // will be handled by SlowStorage
|
|
||||||
$fastStorage->get('bar'); // will be handled by FastStorage
|
|
||||||
|
|
||||||
/**
|
|
||||||
* In this example we could also add a abstract class and extend it to build Fast- and SlowStorage. That class would
|
|
||||||
* then manage the chain and when the cache hits a "miss", it would check if there is a next handler
|
|
||||||
*/
|
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\ChainOfResponsibilities;
|
namespace DesignPatterns\ChainOfResponsibilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -16,7 +12,9 @@ namespace DesignPatterns\ChainOfResponsibilities;
|
|||||||
*/
|
*/
|
||||||
abstract class Handler
|
abstract class Handler
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var Handler
|
||||||
|
*/
|
||||||
private $successor = null;
|
private $successor = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,14 +22,16 @@ abstract class Handler
|
|||||||
*
|
*
|
||||||
* A prepend method could be done with the same spirit
|
* A prepend method could be done with the same spirit
|
||||||
*
|
*
|
||||||
* You could also send the successor in the contructor but in PHP it is a
|
* You could also send the successor in the constructor but in PHP it is a
|
||||||
* bad idea because you have to remove the type-hint of the parameter because
|
* bad idea because you have to remove the type-hint of the parameter because
|
||||||
* the last handler has a null successor.
|
* the last handler has a null successor.
|
||||||
*
|
*
|
||||||
* And if you override the contructor, that Handler can no longer have a
|
* And if you override the constructor, that Handler can no longer have a
|
||||||
* successor. One solution is to provide a NullObject (see pattern).
|
* successor. One solution is to provide a NullObject (see pattern).
|
||||||
* It is more preferable to keep the constructor "free" to inject services
|
* It is more preferable to keep the constructor "free" to inject services
|
||||||
* you need with the DiC of symfony2 for example.
|
* you need with the DiC of symfony2 for example.
|
||||||
|
*
|
||||||
|
* @param Handler $handler
|
||||||
*/
|
*/
|
||||||
final public function append(Handler $handler)
|
final public function append(Handler $handler)
|
||||||
{
|
{
|
||||||
@@ -48,6 +48,10 @@ abstract class Handler
|
|||||||
* This approach by using a template method pattern ensures you that
|
* This approach by using a template method pattern ensures you that
|
||||||
* each subclass will not forget to call the successor. Beside, the returned
|
* each subclass will not forget to call the successor. Beside, the returned
|
||||||
* boolean value indicates you if the request have been processed or not.
|
* boolean value indicates you if the request have been processed or not.
|
||||||
|
*
|
||||||
|
* @param Request $req
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
*/
|
*/
|
||||||
final public function handle(Request $req)
|
final public function handle(Request $req)
|
||||||
{
|
{
|
||||||
@@ -65,8 +69,10 @@ abstract class Handler
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Each concrete handler has to implement the processing of the request
|
* Each concrete handler has to implement the processing of the request
|
||||||
*
|
*
|
||||||
|
* @param Request $req
|
||||||
|
*
|
||||||
* @return bool true if the request has been processed
|
* @return bool true if the request has been processed
|
||||||
*/
|
*/
|
||||||
abstract protected function processing(Request $req);
|
abstract protected function processing(Request $req);
|
||||||
}
|
}
|
||||||
|
13
ChainOfResponsibilities/README.md
Normal file
13
ChainOfResponsibilities/README.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# chain of responsibilities
|
||||||
|
|
||||||
|
## Purpose:
|
||||||
|
|
||||||
|
To build a chain of objects to handle a call. if one object cannot handle a call, it delegates the call to the next
|
||||||
|
in the chain and so forth
|
||||||
|
|
||||||
|
## Examples:
|
||||||
|
|
||||||
|
* logging framework
|
||||||
|
* 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.
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\ChainOfResponsibilities;
|
namespace DesignPatterns\ChainOfResponsibilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,4 +16,4 @@ namespace DesignPatterns\ChainOfResponsibilities;
|
|||||||
class Request
|
class Request
|
||||||
{
|
{
|
||||||
// getter and setter but I don't want to generate to much noise in handlers
|
// getter and setter but I don't want to generate to much noise in handlers
|
||||||
}
|
}
|
||||||
|
@@ -1,30 +1,34 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\ChainOfResponsibilities\Responsible;
|
namespace DesignPatterns\ChainOfResponsibilities\Responsible;
|
||||||
|
|
||||||
use DesignPatterns\ChainOfResponsibilities\Handler;
|
use DesignPatterns\ChainOfResponsibilities\Handler;
|
||||||
use DesignPatterns\ChainOfResponsibilities\Request;
|
use DesignPatterns\ChainOfResponsibilities\Request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class FastStorage
|
||||||
|
*/
|
||||||
class FastStorage extends Handler
|
class FastStorage extends Handler
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $data = array();
|
||||||
|
|
||||||
protected $_data = array();
|
/**
|
||||||
|
* @param array $data
|
||||||
|
*/
|
||||||
public function __construct($data = array())
|
public function __construct($data = array())
|
||||||
{
|
{
|
||||||
$this->_data = $data;
|
$this->data = $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function processing(Request $req)
|
protected function processing(Request $req)
|
||||||
{
|
{
|
||||||
if ('get' === $req->verb) {
|
if ('get' === $req->verb) {
|
||||||
if (array_key_exists($req->key, $this->_data)) {
|
if (array_key_exists($req->key, $this->data)) {
|
||||||
// the handler IS responsible and then processes the request
|
// the handler IS responsible and then processes the request
|
||||||
$req->response = $this->_data[$req->key];
|
$req->response = $this->data[$req->key];
|
||||||
// instead of returning true, I could return the value but it proves
|
// instead of returning true, I could return the value but it proves
|
||||||
// to be a bad idea. What if the value IS "false" ?
|
// to be a bad idea. What if the value IS "false" ?
|
||||||
return true;
|
return true;
|
||||||
@@ -33,5 +37,4 @@ class FastStorage extends Handler
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\ChainOfResponsibilities\Responsible;
|
namespace DesignPatterns\ChainOfResponsibilities\Responsible;
|
||||||
|
|
||||||
use DesignPatterns\ChainOfResponsibilities\Handler;
|
use DesignPatterns\ChainOfResponsibilities\Handler;
|
||||||
@@ -21,24 +17,29 @@ use DesignPatterns\ChainOfResponsibilities\Request;
|
|||||||
*/
|
*/
|
||||||
class SlowStorage extends Handler
|
class SlowStorage extends Handler
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $data = array();
|
||||||
|
|
||||||
protected $_data = array();
|
/**
|
||||||
|
* @param array $data
|
||||||
|
*/
|
||||||
public function __construct($data = array())
|
public function __construct($data = array())
|
||||||
{
|
{
|
||||||
$this->_data = $data;
|
$this->data = $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function processing(Request $req)
|
protected function processing(Request $req)
|
||||||
{
|
{
|
||||||
if ('get' === $req->verb) {
|
if ('get' === $req->verb) {
|
||||||
if (array_key_exists($req->key, $this->_data)) {
|
if (array_key_exists($req->key, $this->data)) {
|
||||||
$req->response = $this->_data[$req->key];
|
$req->response = $this->data[$req->key];
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -23,9 +23,8 @@ namespace DesignPatterns\Command;
|
|||||||
* can be implemented with the Command pattern (e.g. vagrant)
|
* can be implemented with the Command pattern (e.g. vagrant)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
interface Command
|
interface CommandInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* this is the most important method in the Command pattern,
|
* this is the most important method in the Command pattern,
|
||||||
* The Receiver goes in the constructor.
|
* The Receiver goes in the constructor.
|
@@ -6,25 +6,31 @@ namespace DesignPatterns\Command;
|
|||||||
* This concrete command calls "print" on the Receiver, but an external
|
* This concrete command calls "print" on the Receiver, but an external
|
||||||
* invoker just know he can call "execute"
|
* invoker just know he can call "execute"
|
||||||
*/
|
*/
|
||||||
class HelloCommand implements Command
|
class HelloCommand implements CommandInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var Receiver
|
||||||
|
*/
|
||||||
protected $output;
|
protected $output;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Each concrete command is builded with different receivers.
|
* Each concrete command is builded with different receivers.
|
||||||
* Can be one, many, none or even other Command in parameters
|
* Can be one, many, none or even other Command in parameters
|
||||||
|
*
|
||||||
|
* @param Receiver $console
|
||||||
*/
|
*/
|
||||||
public function __construct(Receiver $console)
|
public function __construct(Receiver $console)
|
||||||
{
|
{
|
||||||
$this->output = $console;
|
$this->output = $console;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* execute and output "Hello World"
|
||||||
|
*/
|
||||||
public function execute()
|
public function execute()
|
||||||
{
|
{
|
||||||
// sometimes, there is no receiver and this is the command which
|
// sometimes, there is no receiver and this is the command which
|
||||||
// does all the work
|
// does all the work
|
||||||
$this->output->write('Hello World');
|
$this->output->write('Hello World');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Command;
|
namespace DesignPatterns\Command;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -12,23 +8,29 @@ namespace DesignPatterns\Command;
|
|||||||
*/
|
*/
|
||||||
class Invoker
|
class Invoker
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var CommandInterface
|
||||||
|
*/
|
||||||
protected $command;
|
protected $command;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In the invoker we find this kind of method for subscribing the command.
|
* In the invoker we find this kind of method for subscribing the command.
|
||||||
* There can be also a stack, a list, a fixed set...
|
* There can be also a stack, a list, a fixed set...
|
||||||
|
*
|
||||||
|
* @param CommandInterface $cmd
|
||||||
*/
|
*/
|
||||||
public function setCommand(Command $cmd)
|
public function setCommand(CommandInterface $cmd)
|
||||||
{
|
{
|
||||||
$this->command = $cmd;
|
$this->command = $cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* executes the command
|
||||||
|
*/
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
// here is a key feature of the invoker
|
// here is a key feature of the invoker
|
||||||
// the invoker is the same whatever is the command
|
// the invoker is the same whatever is the command
|
||||||
$this->command->execute();
|
$this->command->execute();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Command;
|
namespace DesignPatterns\Command;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,10 +7,11 @@ namespace DesignPatterns\Command;
|
|||||||
*/
|
*/
|
||||||
class Receiver
|
class Receiver
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @param string $str
|
||||||
|
*/
|
||||||
public function write($str)
|
public function write($str)
|
||||||
{
|
{
|
||||||
echo $str;
|
echo $str;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace DesignPatterns\Composite;
|
namespace DesignPatterns\Composite;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* composite pattern
|
* Composite pattern
|
||||||
*
|
*
|
||||||
* Purpose:
|
* Purpose:
|
||||||
* to treat a group of objects the same way as a single instance of the object
|
* to treat a group of objects the same way as a single instance of the object
|
||||||
@@ -18,7 +18,10 @@ namespace DesignPatterns\Composite;
|
|||||||
*/
|
*/
|
||||||
class Form extends FormElement
|
class Form extends FormElement
|
||||||
{
|
{
|
||||||
protected $_elements;
|
/**
|
||||||
|
* @var array|FormElement[]
|
||||||
|
*/
|
||||||
|
protected $elements;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* runs through all elements and calls render() on them, then returns the complete representation
|
* runs through all elements and calls render() on them, then returns the complete representation
|
||||||
@@ -26,20 +29,26 @@ class Form extends FormElement
|
|||||||
*
|
*
|
||||||
* from the outside, one will not see this and the form will act like a single object instance
|
* from the outside, one will not see this and the form will act like a single object instance
|
||||||
*
|
*
|
||||||
|
* @param int $indent
|
||||||
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function render($indent = 0)
|
public function render($indent = 0)
|
||||||
{
|
{
|
||||||
$formCode = '';
|
$formCode = '';
|
||||||
foreach ($this->_elements as $element) {
|
|
||||||
|
foreach ($this->elements as $element) {
|
||||||
$formCode .= $element->render($indent + 1) . PHP_EOL;
|
$formCode .= $element->render($indent + 1) . PHP_EOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $formCode;
|
return $formCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param FormElement $element
|
||||||
|
*/
|
||||||
public function addElement(FormElement $element)
|
public function addElement(FormElement $element)
|
||||||
{
|
{
|
||||||
$this->_elements[] = $element;
|
$this->elements[] = $element;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,17 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Composite;
|
namespace DesignPatterns\Composite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class FormElement
|
||||||
|
*/
|
||||||
abstract class FormElement
|
abstract class FormElement
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* renders the elements' code
|
||||||
|
*
|
||||||
|
* @param int $indent
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
abstract public function render($indent = 0);
|
abstract public function render($indent = 0);
|
||||||
}
|
}
|
||||||
|
@@ -2,8 +2,18 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Composite;
|
namespace DesignPatterns\Composite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class InputElement
|
||||||
|
*/
|
||||||
class InputElement extends FormElement
|
class InputElement extends FormElement
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* renders the input element HTML
|
||||||
|
*
|
||||||
|
* @param int $indent
|
||||||
|
*
|
||||||
|
* @return mixed|string
|
||||||
|
*/
|
||||||
public function render($indent = 0)
|
public function render($indent = 0)
|
||||||
{
|
{
|
||||||
return str_repeat(' ', $indent) . '<input type="text" />';
|
return str_repeat(' ', $indent) . '<input type="text" />';
|
||||||
|
@@ -2,8 +2,18 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Composite;
|
namespace DesignPatterns\Composite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class TextElement
|
||||||
|
*/
|
||||||
class TextElement extends FormElement
|
class TextElement extends FormElement
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* renders the text element
|
||||||
|
*
|
||||||
|
* @param int $indent
|
||||||
|
*
|
||||||
|
* @return mixed|string
|
||||||
|
*/
|
||||||
public function render($indent = 0)
|
public function render($indent = 0)
|
||||||
{
|
{
|
||||||
return str_repeat(' ', $indent) . 'this is a text element';
|
return str_repeat(' ', $indent) . 'this is a text element';
|
||||||
|
@@ -42,43 +42,48 @@ class User
|
|||||||
/**
|
/**
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getUserId() {
|
public function getUserId()
|
||||||
return $this->userId;
|
{
|
||||||
}
|
return $this->userId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $userId
|
* @param int $userId
|
||||||
*/
|
*/
|
||||||
public function setUserID($userId) {
|
public function setUserID($userId)
|
||||||
$this->userId = $userId;
|
{
|
||||||
}
|
$this->userId = $userId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getUsername() {
|
public function getUsername()
|
||||||
return $this->username;
|
{
|
||||||
}
|
return $this->username;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $username
|
* @param string $username
|
||||||
*/
|
*/
|
||||||
public function setUsername($username) {
|
public function setUsername($username)
|
||||||
$this->username = $username;
|
{
|
||||||
}
|
$this->username = $username;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getEmail() {
|
public function getEmail()
|
||||||
return $this->email;
|
{
|
||||||
}
|
return $this->email;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $email
|
* @param string $email
|
||||||
*/
|
*/
|
||||||
public function setEmail($email) {
|
public function setEmail($email)
|
||||||
$this->email = $email;
|
{
|
||||||
}
|
$this->email = $email;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -25,12 +25,14 @@ namespace DesignPatterns\DataMapper;
|
|||||||
*/
|
*/
|
||||||
class UserMapper
|
class UserMapper
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var DBAL
|
* @var DBAL
|
||||||
*/
|
*/
|
||||||
protected $adapter;
|
protected $adapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param DBAL $dbLayer
|
||||||
|
*/
|
||||||
public function __construct(DBAL $dbLayer)
|
public function __construct(DBAL $dbLayer)
|
||||||
{
|
{
|
||||||
$this->adapter = $dbLayer;
|
$this->adapter = $dbLayer;
|
||||||
@@ -40,6 +42,7 @@ class UserMapper
|
|||||||
* saves a user object from memory to Database
|
* saves a user object from memory to Database
|
||||||
*
|
*
|
||||||
* @param User $user
|
* @param User $user
|
||||||
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function save(User $user)
|
public function save(User $user)
|
||||||
@@ -55,9 +58,11 @@ class UserMapper
|
|||||||
if (null === ($id = $user->getUserId())) {
|
if (null === ($id = $user->getUserId())) {
|
||||||
unset($data['userid']);
|
unset($data['userid']);
|
||||||
$this->adapter->insert($data);
|
$this->adapter->insert($data);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
$this->adapter->update($data, array('userid = ?' => $id));
|
$this->adapter->update($data, array('userid = ?' => $id));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,13 +71,15 @@ class UserMapper
|
|||||||
* finds a user from Database based on ID and returns a User object located
|
* finds a user from Database based on ID and returns a User object located
|
||||||
* in memory
|
* in memory
|
||||||
*
|
*
|
||||||
* @param $id
|
* @param int $id
|
||||||
|
*
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
* @return User
|
* @return User
|
||||||
*/
|
*/
|
||||||
public function findById($id)
|
public function findById($id)
|
||||||
{
|
{
|
||||||
$result = $this->adapter->find($id);
|
$result = $this->adapter->find($id);
|
||||||
|
|
||||||
if (0 == count($result)) {
|
if (0 == count($result)) {
|
||||||
throw new \InvalidArgumentException("User #$id not found");
|
throw new \InvalidArgumentException("User #$id not found");
|
||||||
}
|
}
|
||||||
@@ -104,7 +111,7 @@ class UserMapper
|
|||||||
*
|
*
|
||||||
* @param array $row
|
* @param array $row
|
||||||
*
|
*
|
||||||
* @return \DesignPatterns\DataMapper\User
|
* @return User
|
||||||
*/
|
*/
|
||||||
protected function mapObject(array $row)
|
protected function mapObject(array $row)
|
||||||
{
|
{
|
||||||
|
@@ -16,24 +16,25 @@ namespace DesignPatterns\Decorator;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the Deoorator MUST implement the Renderer contract, this is the key-feature
|
* the Deoorator MUST implement the RendererInterface contract, this is the key-feature
|
||||||
* of this design pattern. If not, this is no longer a Decorator but just a dumb
|
* of this design pattern. If not, this is no longer a Decorator but just a dumb
|
||||||
* wrapper.
|
* wrapper.
|
||||||
*/
|
*/
|
||||||
abstract class Decorator implements Renderer
|
abstract class Decorator implements RendererInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
protected $_wrapped;
|
* @var RendererInterface
|
||||||
|
*/
|
||||||
|
protected $wrapped;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* You must type-hint the wrapped component :
|
* You must type-hint the wrapped component :
|
||||||
* It ensures you can call renderData() in the subclasses !
|
* It ensures you can call renderData() in the subclasses !
|
||||||
*
|
*
|
||||||
* @param Renderer $wrappable
|
* @param RendererInterface $wrappable
|
||||||
*/
|
*/
|
||||||
public function __construct(Renderer $wrappable)
|
public function __construct(RendererInterface $wrappable)
|
||||||
{
|
{
|
||||||
$this->_wrapped = $wrappable;
|
$this->wrapped = $wrappable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,13 +2,20 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Decorator;
|
namespace DesignPatterns\Decorator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class RenderInJson
|
||||||
|
*/
|
||||||
class RenderInJson extends Decorator
|
class RenderInJson extends Decorator
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* render data as JSON
|
||||||
|
*
|
||||||
|
* @return mixed|string
|
||||||
|
*/
|
||||||
public function renderData()
|
public function renderData()
|
||||||
{
|
{
|
||||||
$output = $this->_wrapped->renderData();
|
$output = $this->wrapped->renderData();
|
||||||
|
|
||||||
return json_encode($output);
|
return json_encode($output);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -2,19 +2,28 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Decorator;
|
namespace DesignPatterns\Decorator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class RenderInXml
|
||||||
|
*/
|
||||||
class RenderInXml extends Decorator
|
class RenderInXml extends Decorator
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* render data as XML
|
||||||
|
*
|
||||||
|
* @return mixed|string
|
||||||
|
*/
|
||||||
public function renderData()
|
public function renderData()
|
||||||
{
|
{
|
||||||
$output = $this->_wrapped->renderData();
|
$output = $this->wrapped->renderData();
|
||||||
// do some fany conversion to xml from array ...
|
|
||||||
|
// do some fancy conversion to xml from array ...
|
||||||
|
|
||||||
$doc = new \DOMDocument();
|
$doc = new \DOMDocument();
|
||||||
|
|
||||||
foreach ($output as $key => $val) {
|
foreach ($output as $key => $val) {
|
||||||
$doc->appendChild($doc->createElement('foo', 'bar'));
|
$doc->appendChild($doc->createElement('foo', 'bar'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $doc->saveXML();
|
return $doc->saveXML();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace DesignPatterns\Decorator;
|
|
||||||
|
|
||||||
interface Renderer
|
|
||||||
{
|
|
||||||
|
|
||||||
public function renderData();
|
|
||||||
}
|
|
16
Decorator/RendererInterface.php
Normal file
16
Decorator/RendererInterface.php
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Decorator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class RendererInterface
|
||||||
|
*/
|
||||||
|
interface RendererInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* render data
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function renderData();
|
||||||
|
}
|
@@ -2,19 +2,29 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Decorator;
|
namespace DesignPatterns\Decorator;
|
||||||
|
|
||||||
class Webservice implements Renderer
|
/**
|
||||||
|
* Class Webservice
|
||||||
|
*/
|
||||||
|
class Webservice implements RendererInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
protected $data;
|
||||||
|
|
||||||
protected $_data;
|
/**
|
||||||
|
* @param mixed $data
|
||||||
|
*/
|
||||||
public function __construct($data)
|
public function __construct($data)
|
||||||
{
|
{
|
||||||
$this->_data = $data;
|
$this->data = $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function renderData()
|
public function renderData()
|
||||||
{
|
{
|
||||||
return $this->_data;
|
return $this->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns;
|
namespace DesignPatterns\DependencyInjection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dependency Injection
|
* Dependency Injection
|
||||||
@@ -18,15 +18,20 @@ namespace DesignPatterns;
|
|||||||
*/
|
*/
|
||||||
class Configuration
|
class Configuration
|
||||||
{
|
{
|
||||||
protected $_host;
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $host;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $host
|
* @param string $host
|
||||||
|
*
|
||||||
* @return Configuration
|
* @return Configuration
|
||||||
*/
|
*/
|
||||||
public function setHost($host)
|
public function setHost($host)
|
||||||
{
|
{
|
||||||
$this->_host = $host;
|
$this->host = $host;
|
||||||
|
|
||||||
return $this; // for a fluent interface
|
return $this; // for a fluent interface
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,29 +40,6 @@ class Configuration
|
|||||||
*/
|
*/
|
||||||
public function getHost()
|
public function getHost()
|
||||||
{
|
{
|
||||||
return $this->_host;
|
return $this->host;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Connection
|
|
||||||
{
|
|
||||||
protected $_configuration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* here, Configuration gets injected and Connection will get all that it needs from Configuration
|
|
||||||
* without DI, the configuration would be created directly in Connection, which is not very good
|
|
||||||
* for testing and extending Connection
|
|
||||||
*
|
|
||||||
* @param Configuration $config
|
|
||||||
*/
|
|
||||||
public function __construct(Configuration $config)
|
|
||||||
{
|
|
||||||
$this->_configuration = $config;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function connect()
|
|
||||||
{
|
|
||||||
$host = $this->_configuration->getHost();
|
|
||||||
// ...
|
|
||||||
}
|
}
|
||||||
}
|
}
|
35
DependencyInjection/Connection.php
Normal file
35
DependencyInjection/Connection.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\DependencyInjection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Connection
|
||||||
|
*/
|
||||||
|
class Connection
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Configuration
|
||||||
|
*/
|
||||||
|
protected $configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* here, Configuration gets injected and Connection will get all that it needs from Configuration
|
||||||
|
* without DI, the configuration would be created directly in Connection, which is not very good
|
||||||
|
* for testing and extending Connection
|
||||||
|
*
|
||||||
|
* @param Configuration $config
|
||||||
|
*/
|
||||||
|
public function __construct(Configuration $config)
|
||||||
|
{
|
||||||
|
$this->configuration = $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* connection using the injected config
|
||||||
|
*/
|
||||||
|
public function connect()
|
||||||
|
{
|
||||||
|
$host = $this->configuration->getHost();
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
}
|
31
Facade/BiosInterface.php
Normal file
31
Facade/BiosInterface.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Facade;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BiosInterface
|
||||||
|
*/
|
||||||
|
interface BiosInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* execute the BIOS
|
||||||
|
*/
|
||||||
|
public function execute();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wait for halt
|
||||||
|
*/
|
||||||
|
public function waitForKeyPress();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* launches the OS
|
||||||
|
*
|
||||||
|
* @param OsInterface $os
|
||||||
|
*/
|
||||||
|
public function launch(OsInterface $os);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* power down BIOS
|
||||||
|
*/
|
||||||
|
public function powerDown();
|
||||||
|
}
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Facade;
|
namespace DesignPatterns\Facade;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,31 +24,45 @@ namespace DesignPatterns\Facade;
|
|||||||
*/
|
*/
|
||||||
class Facade
|
class Facade
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var OsInterface
|
||||||
|
*/
|
||||||
|
protected $os;
|
||||||
|
|
||||||
protected $opsys;
|
/**
|
||||||
|
* @var BiosInterface
|
||||||
|
*/
|
||||||
protected $bios;
|
protected $bios;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the perfect time to use a dependency injection container
|
* This is the perfect time to use a dependency injection container
|
||||||
* to creaate an instance of this class
|
* to creaate an instance of this class
|
||||||
|
*
|
||||||
|
* @param BiosInterface $bios
|
||||||
|
* @param OsInterface $os
|
||||||
*/
|
*/
|
||||||
public function __construct(BiosInterface $bios, OsInterface $os)
|
public function __construct(BiosInterface $bios, OsInterface $os)
|
||||||
{
|
{
|
||||||
$this->bios = $bios;
|
$this->bios = $bios;
|
||||||
$this->opsys = $os;
|
$this->os = $os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* turn on the system
|
||||||
|
*/
|
||||||
public function turnOn()
|
public function turnOn()
|
||||||
{
|
{
|
||||||
$this->bios->execute();
|
$this->bios->execute();
|
||||||
$this->bios->waitForKeyPress();
|
$this->bios->waitForKeyPress();
|
||||||
$this->bios->launch($this->opsys);
|
$this->bios->launch($this->os);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* turn off the system
|
||||||
|
*/
|
||||||
public function turnOff()
|
public function turnOff()
|
||||||
{
|
{
|
||||||
$this->opsys->halt();
|
$this->os->halt();
|
||||||
$this->bios->powerDown();
|
$this->bios->powerDown();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
14
Facade/OsInterface.php
Normal file
14
Facade/OsInterface.php
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Facade;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class OsInterface
|
||||||
|
*/
|
||||||
|
interface OsInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* halt the OS
|
||||||
|
*/
|
||||||
|
public function halt();
|
||||||
|
}
|
@@ -1,20 +1,24 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\FactoryMethod;
|
namespace DesignPatterns\FactoryMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bicycle is a bicycle
|
* Bicycle is a bicycle
|
||||||
*/
|
*/
|
||||||
class Bicycle implements Vehicle
|
class Bicycle implements VehicleInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $color;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sets the color of the bicycle
|
||||||
|
*
|
||||||
|
* @param string $rgb
|
||||||
|
*/
|
||||||
public function setColor($rgb)
|
public function setColor($rgb)
|
||||||
{
|
{
|
||||||
|
$this->color = $rgb;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\FactoryMethod;
|
namespace DesignPatterns\FactoryMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,7 +28,7 @@ abstract class FactoryMethod
|
|||||||
*
|
*
|
||||||
* @param string $type a generic type
|
* @param string $type a generic type
|
||||||
*
|
*
|
||||||
* @return Vehicle a new vehicle
|
* @return VehicleInterface a new vehicle
|
||||||
*/
|
*/
|
||||||
abstract protected function createVehicle($type);
|
abstract protected function createVehicle($type);
|
||||||
|
|
||||||
@@ -41,7 +37,7 @@ abstract class FactoryMethod
|
|||||||
*
|
*
|
||||||
* @param int $type
|
* @param int $type
|
||||||
*
|
*
|
||||||
* @return Vehicle a new vehicle
|
* @return VehicleInterface a new vehicle
|
||||||
*/
|
*/
|
||||||
public function create($type)
|
public function create($type)
|
||||||
{
|
{
|
||||||
@@ -50,5 +46,4 @@ abstract class FactoryMethod
|
|||||||
|
|
||||||
return $obj;
|
return $obj;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -1,20 +1,22 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\FactoryMethod;
|
namespace DesignPatterns\FactoryMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ferrari is a italian car
|
* Ferrari is a italian car
|
||||||
*/
|
*/
|
||||||
class Ferrari implements Vehicle
|
class Ferrari implements VehicleInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $color;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $rgb
|
||||||
|
*/
|
||||||
public function setColor($rgb)
|
public function setColor($rgb)
|
||||||
{
|
{
|
||||||
|
$this->color = $rgb;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -1,39 +1,31 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\FactoryMethod;
|
namespace DesignPatterns\FactoryMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GermanFactory is vehicle factory in Germany
|
* GermanFactory is a vehicle factory in Germany
|
||||||
*/
|
*/
|
||||||
class GermanFactory extends FactoryMethod
|
class GermanFactory extends FactoryMethod
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
protected function createVehicle($type)
|
protected function createVehicle($type)
|
||||||
{
|
{
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
|
case parent::CHEAP:
|
||||||
case parent::CHEAP :
|
|
||||||
return new Bicycle();
|
return new Bicycle();
|
||||||
break;
|
break;
|
||||||
|
case parent::FAST:
|
||||||
case parent::FAST :
|
|
||||||
$obj = new Porsche();
|
$obj = new Porsche();
|
||||||
// we can specialize the way we want some concrete Vehicle since
|
// we can specialize the way we want some concrete Vehicle since
|
||||||
// we know the class
|
// we know the class
|
||||||
$obj->addTuningAMG();
|
$obj->addTuningAMG();
|
||||||
|
|
||||||
return $obj;
|
return $obj;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
default :
|
|
||||||
throw new \InvalidArgumentException("$type is not a valid vehicle");
|
throw new \InvalidArgumentException("$type is not a valid vehicle");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\FactoryMethod;
|
namespace DesignPatterns\FactoryMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,25 +7,20 @@ namespace DesignPatterns\FactoryMethod;
|
|||||||
*/
|
*/
|
||||||
class ItalianFactory extends FactoryMethod
|
class ItalianFactory extends FactoryMethod
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
protected function createVehicle($type)
|
protected function createVehicle($type)
|
||||||
{
|
{
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
|
case parent::CHEAP:
|
||||||
case parent::CHEAP :
|
|
||||||
return new Bicycle();
|
return new Bicycle();
|
||||||
break;
|
break;
|
||||||
|
case parent::FAST:
|
||||||
case parent::FAST :
|
|
||||||
return new Ferrari();
|
return new Ferrari();
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
default :
|
|
||||||
throw new \InvalidArgumentException("$type is not a valid vehicle");
|
throw new \InvalidArgumentException("$type is not a valid vehicle");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -1,25 +1,31 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\FactoryMethod;
|
namespace DesignPatterns\FactoryMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Porsche is a german car
|
* Porsche is a german car
|
||||||
*/
|
*/
|
||||||
class Porsche implements Vehicle
|
class Porsche implements VehicleInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $color;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $rgb
|
||||||
|
*/
|
||||||
public function setColor($rgb)
|
public function setColor($rgb)
|
||||||
{
|
{
|
||||||
|
$this->color = $rgb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* although tuning by AMG is only offered for Mercedes Cars,
|
||||||
|
* this is a valid coding example ...
|
||||||
|
*/
|
||||||
public function addTuningAMG()
|
public function addTuningAMG()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@@ -1,16 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\FactoryMethod;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Vehicle is a contract for a vehicle
|
|
||||||
*/
|
|
||||||
interface Vehicle
|
|
||||||
{
|
|
||||||
|
|
||||||
function setColor($rgb);
|
|
||||||
}
|
|
16
FactoryMethod/VehicleInterface.php
Normal file
16
FactoryMethod/VehicleInterface.php
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\FactoryMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VehicleInterface is a contract for a vehicle
|
||||||
|
*/
|
||||||
|
interface VehicleInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* sets the color of the vehicle
|
||||||
|
*
|
||||||
|
* @param string $rgb
|
||||||
|
*/
|
||||||
|
public function setColor($rgb);
|
||||||
|
}
|
@@ -11,56 +11,78 @@ namespace DesignPatterns\FluentInterface;
|
|||||||
* Examples:
|
* Examples:
|
||||||
* - Doctrine2's QueryBuilder works something like that example class below
|
* - Doctrine2's QueryBuilder works something like that example class below
|
||||||
* - PHPUnit uses fluent interfaces to build mock objects
|
* - PHPUnit uses fluent interfaces to build mock objects
|
||||||
* - Yii Framework: CDbCommand and CActiveRecord use this pattern too
|
* - Yii Framework: CDbCommand and CActiveRecord use this pattern, too
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
class SQL
|
class SQL
|
||||||
{
|
{
|
||||||
protected $_fields = array();
|
/**
|
||||||
protected $_from = array();
|
* @var array
|
||||||
protected $_where = array();
|
*/
|
||||||
|
protected $fields = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $from = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $where = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* adds select fields
|
||||||
*
|
*
|
||||||
* @param array $fields
|
* @param array $fields
|
||||||
|
*
|
||||||
* @return SQL
|
* @return SQL
|
||||||
*/
|
*/
|
||||||
public function select(array $fields = array())
|
public function select(array $fields = array())
|
||||||
{
|
{
|
||||||
$this->_fields = $fields;
|
$this->fields = $fields;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* adds a FROM clause
|
||||||
*
|
*
|
||||||
* @param string $table
|
* @param string $table
|
||||||
* @param string $alias
|
* @param string $alias
|
||||||
|
*
|
||||||
* @return SQL
|
* @return SQL
|
||||||
*/
|
*/
|
||||||
public function from($table, $alias)
|
public function from($table, $alias)
|
||||||
{
|
{
|
||||||
$this->_from[] = $table . ' AS ' . $alias;
|
$this->from[] = $table . ' AS ' . $alias;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* adds a WHERE condition
|
||||||
|
*
|
||||||
* @param string $condition
|
* @param string $condition
|
||||||
|
*
|
||||||
* @return SQL
|
* @return SQL
|
||||||
*/
|
*/
|
||||||
public function where($condition)
|
public function where($condition)
|
||||||
{
|
{
|
||||||
$this->_where[] = $condition;
|
$this->where[] = $condition;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the query, just an example of building a query,
|
* Gets the query, just an example of building a query,
|
||||||
* no check on consistency
|
* no check on consistency
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getQuery()
|
public function getQuery()
|
||||||
{
|
{
|
||||||
return 'SELECT ' . implode(',', $this->_fields)
|
return 'SELECT ' . implode(',', $this->fields)
|
||||||
. ' FROM ' . implode(',', $this->_from)
|
. ' FROM ' . implode(',', $this->from)
|
||||||
. ' WHERE ' . implode(' AND ', $this->_where);
|
. ' WHERE ' . implode(' AND ', $this->where);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,80 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Iterator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Iterator provides a standard way to iterate over a collection without knowing
|
|
||||||
* how it is implemented. All you need to know is : you can traverse it
|
|
||||||
* with current, valid, next, rewind and key.
|
|
||||||
*
|
|
||||||
* That's the key feature of this pattern :
|
|
||||||
* The underlaying machinery could be an array, a matrix, a file, a cursor
|
|
||||||
* from database, a webservice with a cache, you don't care anymore.
|
|
||||||
*
|
|
||||||
* Note: This design pattern changes from one language to another. It depends
|
|
||||||
* mostly how loop statements handle collections (see Java before and after 1.5)
|
|
||||||
*
|
|
||||||
* In this simple example, I try to demonstrate how I manage a "linear" iterator
|
|
||||||
* on a card game but in fact, the underlaying storage is handled by two combined
|
|
||||||
* arrays.
|
|
||||||
*
|
|
||||||
* If tomorrow you decide to read cards from a database, the client
|
|
||||||
* (see the PHPUnit test) will remain unchanged. That's the beauty of it.
|
|
||||||
*/
|
|
||||||
class CardGame implements \Iterator
|
|
||||||
{
|
|
||||||
|
|
||||||
protected $color = array('D', 'S', 'C', 'H');
|
|
||||||
protected $number = array(7, 8, 9, 10, 'J', 'Q', 'K', 'A');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the current value
|
|
||||||
*/
|
|
||||||
public function current()
|
|
||||||
{
|
|
||||||
return current($this->number) . ' of ' . current($this->color);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the current key
|
|
||||||
*/
|
|
||||||
public function key()
|
|
||||||
{
|
|
||||||
return current($this->color) . current($this->number);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Go to the next item in the collection
|
|
||||||
*/
|
|
||||||
public function next()
|
|
||||||
{
|
|
||||||
if (false === next($this->number)) {
|
|
||||||
if (false !== next($this->color)) {
|
|
||||||
reset($this->number);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Go to the first item in the collection
|
|
||||||
*/
|
|
||||||
public function rewind()
|
|
||||||
{
|
|
||||||
reset($this->color);
|
|
||||||
reset($this->number);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is the current position a valid item (true)
|
|
||||||
* or do we reach the end (false) ?
|
|
||||||
*/
|
|
||||||
public function valid()
|
|
||||||
{
|
|
||||||
return current($this->number) || current($this->color);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
51
Iterator/File.php
Normal file
51
Iterator/File.php
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* iterator pattern
|
||||||
|
*
|
||||||
|
* Purpose:
|
||||||
|
* to make an object iterable
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* THIS EXAMPLE ALSO APPLIES THE COMPOSITE PATTERN
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class File
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var RowSet
|
||||||
|
*/
|
||||||
|
protected $rowSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $pathName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $pathName
|
||||||
|
*/
|
||||||
|
public function __construct($pathName)
|
||||||
|
{
|
||||||
|
$this->rowSet = new Rowset($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* processes the rowSet
|
||||||
|
*/
|
||||||
|
public function process()
|
||||||
|
{
|
||||||
|
// this is the place to show how using an iterator, with foreach
|
||||||
|
// See the CardGame.php file
|
||||||
|
$this->rowSet->process();
|
||||||
|
}
|
||||||
|
}
|
@@ -1,119 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace DesignPatterns;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* iterator pattern
|
|
||||||
*
|
|
||||||
* Purpose:
|
|
||||||
* to make an object iterable
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* THIS EXAMPLE ALSO APPLIES THE COMPOSITE PATTERN
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class File
|
|
||||||
{
|
|
||||||
protected $_rowset;
|
|
||||||
|
|
||||||
protected $_pathName;
|
|
||||||
|
|
||||||
public function __construct($pathName)
|
|
||||||
{
|
|
||||||
$this->_rowset = new Rowset($this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function process()
|
|
||||||
{
|
|
||||||
// this is the place to show how using an iterator, with foreach
|
|
||||||
// See the CardGame.php file
|
|
||||||
$this->_rowset->process();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Rowset implements \Iterator
|
|
||||||
{
|
|
||||||
protected $_currentRow;
|
|
||||||
|
|
||||||
protected $_file;
|
|
||||||
|
|
||||||
public function __construct($file)
|
|
||||||
{
|
|
||||||
$this->_file = $file;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* composite pattern: run through all rows and process them
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function process()
|
|
||||||
{
|
|
||||||
// this actually calls rewind(), { next(), valid(), key() and current() :}
|
|
||||||
/**
|
|
||||||
* THE key feature of the Iterator Pattern is to provide a *public contract*
|
|
||||||
* to iterate on a collection without knowing how items are handled inside
|
|
||||||
* the collection. It is not just an easy way to use "foreach"
|
|
||||||
*
|
|
||||||
* One cannot see the point of iterator pattern if you iterate on $this.
|
|
||||||
* This example is unclear and mixed with some Composite pattern ideas.
|
|
||||||
*/
|
|
||||||
foreach ($this as $line => $row) {
|
|
||||||
$row->process();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function rewind()
|
|
||||||
{
|
|
||||||
// seek to first line from $this->_file
|
|
||||||
}
|
|
||||||
|
|
||||||
public function next()
|
|
||||||
{
|
|
||||||
// read the next line from $this->_file
|
|
||||||
if (!$eof) {
|
|
||||||
$data = ''; // get the line
|
|
||||||
$this->_currentRow = new Row($data);
|
|
||||||
} else {
|
|
||||||
$this->_currentRow = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function current()
|
|
||||||
{
|
|
||||||
return $this->_currentRow;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function valid()
|
|
||||||
{
|
|
||||||
return null !== $this->_currentRow;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function key()
|
|
||||||
{
|
|
||||||
// you would want to increment this in next() or whatsoever
|
|
||||||
return $this->_lineNumber;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Row
|
|
||||||
{
|
|
||||||
protected $_data;
|
|
||||||
|
|
||||||
public function __construct($data)
|
|
||||||
{
|
|
||||||
$this->_data = $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function process()
|
|
||||||
{
|
|
||||||
// do some fancy things here ...
|
|
||||||
}
|
|
||||||
}
|
|
27
Iterator/Row.php
Normal file
27
Iterator/Row.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Row
|
||||||
|
*/
|
||||||
|
class Row
|
||||||
|
{
|
||||||
|
protected $data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function __construct($data)
|
||||||
|
{
|
||||||
|
$this->data = $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function process()
|
||||||
|
{
|
||||||
|
// do some fancy things here ...
|
||||||
|
}
|
||||||
|
}
|
100
Iterator/RowSet.php
Normal file
100
Iterator/RowSet.php
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class RowSet
|
||||||
|
*/
|
||||||
|
class RowSet implements \Iterator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var
|
||||||
|
*/
|
||||||
|
protected $currentRow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $lineNumber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $file
|
||||||
|
*/
|
||||||
|
public function __construct($file)
|
||||||
|
{
|
||||||
|
$this->file = $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* composite pattern: run through all rows and process them
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function process()
|
||||||
|
{
|
||||||
|
// this actually calls rewind(), { next(), valid(), key() and current() :}
|
||||||
|
/**
|
||||||
|
* THE key feature of the Iterator Pattern is to provide a *public contract*
|
||||||
|
* to iterate on a collection without knowing how items are handled inside
|
||||||
|
* the collection. It is not just an easy way to use "foreach"
|
||||||
|
*
|
||||||
|
* One cannot see the point of iterator pattern if you iterate on $this.
|
||||||
|
* This example is unclear and mixed with some Composite pattern ideas.
|
||||||
|
*/
|
||||||
|
foreach ($this as $line => $row) {
|
||||||
|
$row->process();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function rewind()
|
||||||
|
{
|
||||||
|
// seek to first line from $this->file
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function next()
|
||||||
|
{
|
||||||
|
// read the next line from $this->file
|
||||||
|
if (!$eof) {
|
||||||
|
$data = ''; // get the line
|
||||||
|
$this->currentRow = new Row($data);
|
||||||
|
} else {
|
||||||
|
$this->currentRow = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function current()
|
||||||
|
{
|
||||||
|
return $this->currentRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function valid()
|
||||||
|
{
|
||||||
|
return null !== $this->currentRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function key()
|
||||||
|
{
|
||||||
|
// you would want to increment this in next() or whatsoever
|
||||||
|
return $this->lineNumber;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Mediator;
|
namespace DesignPatterns\Mediator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -12,8 +8,11 @@ namespace DesignPatterns\Mediator;
|
|||||||
*/
|
*/
|
||||||
abstract class Colleague
|
abstract class Colleague
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
// this ensures no change in subclasses
|
* this ensures no change in subclasses
|
||||||
|
*
|
||||||
|
* @var MediatorInterface
|
||||||
|
*/
|
||||||
private $mediator;
|
private $mediator;
|
||||||
|
|
||||||
// for subclasses
|
// for subclasses
|
||||||
@@ -22,10 +21,12 @@ abstract class Colleague
|
|||||||
return $this->mediator;
|
return $this->mediator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param MediatorInterface $medium
|
||||||
|
*/
|
||||||
public function __construct(MediatorInterface $medium)
|
public function __construct(MediatorInterface $medium)
|
||||||
{
|
{
|
||||||
// in this way, we are sure the concrete colleague knows the mediator
|
// in this way, we are sure the concrete colleague knows the mediator
|
||||||
$this->mediator = $medium;
|
$this->mediator = $medium;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Mediator;
|
namespace DesignPatterns\Mediator;
|
||||||
|
|
||||||
use DesignPatterns\Mediator\Subsystem;
|
use DesignPatterns\Mediator\Subsystem;
|
||||||
@@ -29,6 +25,11 @@ class Mediator implements MediatorInterface
|
|||||||
protected $database;
|
protected $database;
|
||||||
protected $client;
|
protected $client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Subsystem\Database $db
|
||||||
|
* @param Subsystem\Client $cl
|
||||||
|
* @param Subsystem\Server $srv
|
||||||
|
*/
|
||||||
public function setColleague(Subsystem\Database $db, Subsystem\Client $cl, Subsystem\Server $srv)
|
public function setColleague(Subsystem\Database $db, Subsystem\Client $cl, Subsystem\Server $srv)
|
||||||
{
|
{
|
||||||
$this->database = $db;
|
$this->database = $db;
|
||||||
@@ -36,19 +37,31 @@ class Mediator implements MediatorInterface
|
|||||||
$this->client = $cl;
|
$this->client = $cl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* make request
|
||||||
|
*/
|
||||||
public function makeRequest()
|
public function makeRequest()
|
||||||
{
|
{
|
||||||
$this->server->process();
|
$this->server->process();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* query db
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function queryDb()
|
public function queryDb()
|
||||||
{
|
{
|
||||||
return $this->database->getData();
|
return $this->database->getData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* send response
|
||||||
|
*
|
||||||
|
* @param string $content
|
||||||
|
*/
|
||||||
public function sendResponse($content)
|
public function sendResponse($content)
|
||||||
{
|
{
|
||||||
$this->client->output($content);
|
$this->client->output($content);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Mediator;
|
namespace DesignPatterns\Mediator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -12,10 +8,20 @@ namespace DesignPatterns\Mediator;
|
|||||||
*/
|
*/
|
||||||
interface MediatorInterface
|
interface MediatorInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* sends the response
|
||||||
|
*
|
||||||
|
* @param string $content
|
||||||
|
*/
|
||||||
|
public function sendResponse($content);
|
||||||
|
|
||||||
function sendResponse($content);
|
/**
|
||||||
|
* makes a request
|
||||||
|
*/
|
||||||
|
public function makeRequest();
|
||||||
|
|
||||||
function makeRequest();
|
/**
|
||||||
|
* queries the DB
|
||||||
function queryDb();
|
*/
|
||||||
}
|
public function queryDb();
|
||||||
|
}
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Mediator\Subsystem;
|
namespace DesignPatterns\Mediator\Subsystem;
|
||||||
|
|
||||||
use DesignPatterns\Mediator\Colleague;
|
use DesignPatterns\Mediator\Colleague;
|
||||||
@@ -13,15 +9,21 @@ use DesignPatterns\Mediator\Colleague;
|
|||||||
*/
|
*/
|
||||||
class Client extends Colleague
|
class Client extends Colleague
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* request
|
||||||
|
*/
|
||||||
public function request()
|
public function request()
|
||||||
{
|
{
|
||||||
$this->getMediator()->makeRequest();
|
$this->getMediator()->makeRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* output content
|
||||||
|
*
|
||||||
|
* @param string $content
|
||||||
|
*/
|
||||||
public function output($content)
|
public function output($content)
|
||||||
{
|
{
|
||||||
echo $content;
|
echo $content;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Mediator\Subsystem;
|
namespace DesignPatterns\Mediator\Subsystem;
|
||||||
|
|
||||||
use DesignPatterns\Mediator\Colleague;
|
use DesignPatterns\Mediator\Colleague;
|
||||||
@@ -13,10 +9,11 @@ use DesignPatterns\Mediator\Colleague;
|
|||||||
*/
|
*/
|
||||||
class Database extends Colleague
|
class Database extends Colleague
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function getData()
|
public function getData()
|
||||||
{
|
{
|
||||||
return "World";
|
return "World";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\Mediator\Subsystem;
|
namespace DesignPatterns\Mediator\Subsystem;
|
||||||
|
|
||||||
use DesignPatterns\Mediator\Colleague;
|
use DesignPatterns\Mediator\Colleague;
|
||||||
@@ -13,11 +9,12 @@ use DesignPatterns\Mediator\Colleague;
|
|||||||
*/
|
*/
|
||||||
class Server extends Colleague
|
class Server extends Colleague
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* process on server
|
||||||
|
*/
|
||||||
public function process()
|
public function process()
|
||||||
{
|
{
|
||||||
$data = $this->getMediator()->queryDb();
|
$data = $this->getMediator()->queryDb();
|
||||||
$this->getMediator()->sendResponse("Hello $data");
|
$this->getMediator()->sendResponse("Hello $data");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -37,7 +37,7 @@ class Multiton
|
|||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private static $_instances = array();
|
private static $instances = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* should not be called from outside: private!
|
* should not be called from outside: private!
|
||||||
@@ -53,15 +53,16 @@ class Multiton
|
|||||||
* uses lazy initialization
|
* uses lazy initialization
|
||||||
*
|
*
|
||||||
* @param string $instanceName
|
* @param string $instanceName
|
||||||
|
*
|
||||||
* @return Multiton
|
* @return Multiton
|
||||||
*/
|
*/
|
||||||
public static function getInstance($instanceName)
|
public static function getInstance($instanceName)
|
||||||
{
|
{
|
||||||
if ( ! array_key_exists($instanceName, self::$_instances)) {
|
if (!array_key_exists($instanceName, self::$instances)) {
|
||||||
self::$_instances[$instanceName] = new self();
|
self::$instances[$instanceName] = new self();
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$_instances[$instanceName];
|
return self::$instances[$instanceName];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,18 +1,18 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\NullObject;
|
namespace DesignPatterns\NullObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LoggerInterface is a contract for logging something
|
* LoggerInterface is a contract for logging something
|
||||||
*
|
*
|
||||||
* Key-feaature : NullLogger MUST inherit from this interface like any other Loggers
|
* Key feature: NullLogger MUST inherit from this interface like any other Loggers
|
||||||
*/
|
*/
|
||||||
interface LoggerInterface
|
interface LoggerInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @param string $str
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function log($str);
|
public function log($str);
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\NullObject;
|
namespace DesignPatterns\NullObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,10 +28,11 @@ namespace DesignPatterns\NullObject;
|
|||||||
*/
|
*/
|
||||||
class NullLogger implements LoggerInterface
|
class NullLogger implements LoggerInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @param string $str
|
||||||
|
*/
|
||||||
public function log($str)
|
public function log($str)
|
||||||
{
|
{
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\NullObject;
|
namespace DesignPatterns\NullObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,10 +7,11 @@ namespace DesignPatterns\NullObject;
|
|||||||
*/
|
*/
|
||||||
class PrintLogger implements LoggerInterface
|
class PrintLogger implements LoggerInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @param string $str
|
||||||
|
*/
|
||||||
public function log($str)
|
public function log($str)
|
||||||
{
|
{
|
||||||
echo $str;
|
echo $str;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\NullObject;
|
namespace DesignPatterns\NullObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,20 +7,28 @@ namespace DesignPatterns\NullObject;
|
|||||||
*/
|
*/
|
||||||
class Service
|
class Service
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var LoggerInterface
|
||||||
|
*/
|
||||||
protected $logger;
|
protected $logger;
|
||||||
|
|
||||||
// we inject the logger in ctor and it is mandatory
|
/**
|
||||||
|
* we inject the logger in ctor and it is mandatory
|
||||||
|
*
|
||||||
|
* @param LoggerInterface $log
|
||||||
|
*/
|
||||||
public function __construct(LoggerInterface $log)
|
public function __construct(LoggerInterface $log)
|
||||||
{
|
{
|
||||||
$this->logger = $log;
|
$this->logger = $log;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* do something ...
|
||||||
|
*/
|
||||||
public function doSomething()
|
public function doSomething()
|
||||||
{
|
{
|
||||||
// no more check "if (!is_null($this->logger))..." with the NullObject pattern
|
// no more check "if (!is_null($this->logger))..." with the NullObject pattern
|
||||||
$this->logger->log('We are in ' . __METHOD__);
|
$this->logger->log('We are in ' . __METHOD__);
|
||||||
// something to do...
|
// something to do...
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -10,49 +10,57 @@ namespace DesignPatterns\Observer;
|
|||||||
*/
|
*/
|
||||||
class User implements \SplSubject
|
class User implements \SplSubject
|
||||||
{
|
{
|
||||||
|
|
||||||
protected $_data = array();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* user data
|
||||||
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $_observers = array();
|
protected $data = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* observers
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $observers = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* attach a new observer
|
* attach a new observer
|
||||||
*
|
*
|
||||||
* @param \SplObserver $observer
|
* @param \SplObserver $observer
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function attach(\SplObserver $observer)
|
public function attach(\SplObserver $observer)
|
||||||
{
|
{
|
||||||
$this->_observers[] = $observer;
|
$this->observers[] = $observer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* detach an observer
|
* detach an observer
|
||||||
*
|
*
|
||||||
* @param \SplObserver $observer
|
* @param \SplObserver $observer
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function detach(\SplObserver $observer)
|
public function detach(\SplObserver $observer)
|
||||||
{
|
{
|
||||||
$index = array_search($observer, $this->_observers);
|
$index = array_search($observer, $this->observers);
|
||||||
|
|
||||||
if (false !== $index) {
|
if (false !== $index) {
|
||||||
unset($this->_observers[$index]);
|
unset($this->observers[$index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* notify observers
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function notify()
|
public function notify()
|
||||||
{
|
{
|
||||||
/** @var SplObserver $observer */
|
/** @var SplObserver $observer */
|
||||||
foreach ($this->_observers as $observer) {
|
foreach ($this->observers as $observer) {
|
||||||
$observer->update($this);
|
$observer->update($this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,17 +69,16 @@ class User implements \SplSubject
|
|||||||
* Ideally one would better write setter/getter for all valid attributes and only call notify()
|
* Ideally one would better write setter/getter for all valid attributes and only call notify()
|
||||||
* on attributes that matter when changed
|
* on attributes that matter when changed
|
||||||
*
|
*
|
||||||
* @param $name
|
* @param string $name
|
||||||
* @param $value
|
* @param mixed $value
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __set($name, $value)
|
public function __set($name, $value)
|
||||||
{
|
{
|
||||||
$this->_data[$name] = $value;
|
$this->data[$name] = $value;
|
||||||
|
|
||||||
// notify the observers, that user has been updated
|
// notify the observers, that user has been updated
|
||||||
$this->notify();
|
$this->notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -17,7 +17,6 @@ namespace DesignPatterns\Observer;
|
|||||||
*/
|
*/
|
||||||
class UserObserver implements \SplObserver
|
class UserObserver implements \SplObserver
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the only method to implement as an observer.
|
* This is the only method to implement as an observer.
|
||||||
* It is called by the Subject (usually by SplSubject::notify() )
|
* It is called by the Subject (usually by SplSubject::notify() )
|
||||||
@@ -28,5 +27,4 @@ class UserObserver implements \SplObserver
|
|||||||
{
|
{
|
||||||
echo get_class($subject) . ' has been updated';
|
echo get_class($subject) . ' has been updated';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
22
Prototype/BarBookPrototype.php
Normal file
22
Prototype/BarBookPrototype.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Prototype;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BarBookPrototype
|
||||||
|
*/
|
||||||
|
class BarBookPrototype extends BookPrototype
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $category = 'Bar';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* empty clone
|
||||||
|
*/
|
||||||
|
public function __clone()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
48
Prototype/BookPrototype.php
Normal file
48
Prototype/BookPrototype.php
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Prototype;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prototype pattern
|
||||||
|
*
|
||||||
|
* 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)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
abstract class BookPrototype
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $category;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
abstract public function __clone();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getTitle()
|
||||||
|
{
|
||||||
|
return $this->title;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $title
|
||||||
|
*/
|
||||||
|
public function setTitle($title)
|
||||||
|
{
|
||||||
|
$this->title = $title;
|
||||||
|
}
|
||||||
|
}
|
19
Prototype/FooBookPrototype.php
Normal file
19
Prototype/FooBookPrototype.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Prototype;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class FooBookPrototype
|
||||||
|
*/
|
||||||
|
class FooBookPrototype extends BookPrototype
|
||||||
|
{
|
||||||
|
protected $category = 'Foo';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* empty clone
|
||||||
|
*/
|
||||||
|
public function __clone()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -1,65 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace DesignPatterns;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prototype pattern
|
|
||||||
*
|
|
||||||
* 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)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
abstract class BookPrototype
|
|
||||||
{
|
|
||||||
protected $_title;
|
|
||||||
protected $_category;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
abstract public function __clone();
|
|
||||||
|
|
||||||
public function getTitle()
|
|
||||||
{
|
|
||||||
return $this->_title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setTitle($title)
|
|
||||||
{
|
|
||||||
$this->_title = $title;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class FooBookPrototype extends BookPrototype
|
|
||||||
{
|
|
||||||
protected $_category = 'Foo';
|
|
||||||
|
|
||||||
public function __clone()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class BarBookPrototype extends BookPrototype
|
|
||||||
{
|
|
||||||
protected $_category = 'Bar';
|
|
||||||
|
|
||||||
|
|
||||||
public function __clone()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$fooPrototype = new FooBookPrototype();
|
|
||||||
$barPrototype = new BarBookPrototype();
|
|
||||||
|
|
||||||
// now lets say we need 10,000 books of foo and 5,000 of bar ...
|
|
||||||
for ($i = 0; $i < 10000; $i++) {
|
|
||||||
$book = clone $fooPrototype;
|
|
||||||
$book->setTitle('Foo Book No ' . $i);
|
|
||||||
}
|
|
12
Prototype/index.php
Normal file
12
Prototype/index.php
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Prototype;
|
||||||
|
|
||||||
|
$fooPrototype = new FooBookPrototype();
|
||||||
|
$barPrototype = new BarBookPrototype();
|
||||||
|
|
||||||
|
// now lets say we need 10,000 books of foo and 5,000 of bar ...
|
||||||
|
for ($i = 0; $i < 10000; $i++) {
|
||||||
|
$book = clone $fooPrototype;
|
||||||
|
$book->setTitle('Foo Book No ' . $i);
|
||||||
|
}
|
@@ -1,94 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace DesignPatterns;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Proxy pattern
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class Record
|
|
||||||
{
|
|
||||||
protected $_data;
|
|
||||||
|
|
||||||
public function __construct($data = null)
|
|
||||||
{
|
|
||||||
$this->_data = $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* magic setter
|
|
||||||
*
|
|
||||||
* @param string $name
|
|
||||||
* @param mixed $value
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function __set($name, $value)
|
|
||||||
{
|
|
||||||
$this->_data[(string) $name] = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* magic getter
|
|
||||||
*
|
|
||||||
* @param string $name
|
|
||||||
* @return mixed|null
|
|
||||||
*/
|
|
||||||
public function __get($name)
|
|
||||||
{
|
|
||||||
if (array_key_exists($name, $this->_data)) {
|
|
||||||
return $this->_data[(string) $name];
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class RecordProxy extends Record
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
protected $_isDirty = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
protected $_isInitialized = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array
|
|
||||||
*/
|
|
||||||
public function __construct($data)
|
|
||||||
{
|
|
||||||
parent::__construct($data);
|
|
||||||
|
|
||||||
// when the record has data, mark it as initialized
|
|
||||||
// since Record will hold our business logic, we don't want to
|
|
||||||
// implement this behaviour there, but instead in a new proxy class
|
|
||||||
// that extends the Record class
|
|
||||||
if (null !== $data) {
|
|
||||||
$this->_isInitialized = true;
|
|
||||||
$this->_isDirty = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* magic setter
|
|
||||||
*
|
|
||||||
* @param string $name
|
|
||||||
* @param mixed $value
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function __set($name, $value)
|
|
||||||
{
|
|
||||||
$this->_isDirty = true;
|
|
||||||
parent::__set($name, $value);
|
|
||||||
}
|
|
||||||
}
|
|
59
Proxy/Record.php
Normal file
59
Proxy/Record.php
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Proxy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proxy pattern
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class Record
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array|null
|
||||||
|
*/
|
||||||
|
protected $data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param null $data
|
||||||
|
*/
|
||||||
|
public function __construct($data = null)
|
||||||
|
{
|
||||||
|
$this->data = (array) $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* magic setter
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param mixed $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __set($name, $value)
|
||||||
|
{
|
||||||
|
$this->data[(string) $name] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* magic getter
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
*
|
||||||
|
* @return mixed|null
|
||||||
|
*/
|
||||||
|
public function __get($name)
|
||||||
|
{
|
||||||
|
if (array_key_exists($name, $this->data)) {
|
||||||
|
return $this->data[(string) $name];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
Proxy/RecordProxy.php
Normal file
50
Proxy/RecordProxy.php
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Proxy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class RecordProxy
|
||||||
|
*/
|
||||||
|
class RecordProxy extends Record
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $isDirty = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $isInitialized = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $data
|
||||||
|
*/
|
||||||
|
public function __construct($data)
|
||||||
|
{
|
||||||
|
parent::__construct($data);
|
||||||
|
|
||||||
|
// when the record has data, mark it as initialized
|
||||||
|
// since Record will hold our business logic, we don't want to
|
||||||
|
// implement this behaviour there, but instead in a new proxy class
|
||||||
|
// that extends the Record class
|
||||||
|
if (null !== $data) {
|
||||||
|
$this->isInitialized = true;
|
||||||
|
$this->isDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* magic setter
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param mixed $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __set($name, $value)
|
||||||
|
{
|
||||||
|
$this->isDirty = true;
|
||||||
|
parent::__set($name, $value);
|
||||||
|
}
|
||||||
|
}
|
@@ -49,6 +49,7 @@ The patterns can be structured in roughly three different categories. Please cli
|
|||||||
## Contribute
|
## Contribute
|
||||||
|
|
||||||
Please feel free to fork and extend existing or add your own examples and send a pull request with your changes!
|
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](https://github.com/squizlabs/PHP_CodeSniffer) against [this standard](https://github.com/domnikl/Symfony2-coding-standard).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
@@ -14,39 +14,41 @@ namespace DesignPatterns;
|
|||||||
* - Yii Framework: CWebApplication holds all the application components, such as CWebUser, CUrlManager, etc.
|
* - Yii Framework: CWebApplication holds all the application components, such as CWebUser, CUrlManager, etc.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
abstract class Registry
|
abstract class Registry
|
||||||
{
|
{
|
||||||
const LOGGER = 'logger';
|
const LOGGER = 'logger';
|
||||||
|
|
||||||
protected static $_storedValues;
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected static $storedValues = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @static
|
* sets a value
|
||||||
|
*
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
|
*
|
||||||
|
* @static
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function set($key, $value)
|
public static function set($key, $value)
|
||||||
{
|
{
|
||||||
self::$_storedValues[$key] = $value;
|
self::$storedValues[$key] = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @static
|
* gets a value from the registry
|
||||||
|
*
|
||||||
* @param string $key
|
* @param string $key
|
||||||
|
*
|
||||||
|
* @static
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public static function get($key)
|
public static function get($key)
|
||||||
{
|
{
|
||||||
return self::$_storedValues[$key];
|
return self::$storedValues[$key];
|
||||||
}
|
}
|
||||||
|
|
||||||
// typically there would be methods to check if a key has already been registered and so on ...
|
// typically there would be methods to check if a key has already been registered and so on ...
|
||||||
}
|
}
|
||||||
|
|
||||||
// while bootstraping the application
|
|
||||||
Registry::set(Registry::LOGGER, new \StdClass());
|
|
||||||
|
|
||||||
// throughout the application
|
|
||||||
Registry::get(Registry::LOGGER)->log('foo');
|
|
9
Registry/index.php
Normal file
9
Registry/index.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use DesignPatterns\Registry;
|
||||||
|
|
||||||
|
// while bootstrapping the application
|
||||||
|
Registry::set(Registry::LOGGER, new \StdClass());
|
||||||
|
|
||||||
|
// throughout the application
|
||||||
|
Registry::get(Registry::LOGGER)->log('foo');
|
@@ -1,20 +1,19 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\SimpleFactory;
|
namespace DesignPatterns\SimpleFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bicycle is a bicycle
|
* Bicycle is a bicycle
|
||||||
*/
|
*/
|
||||||
class Bicycle implements Vehicle
|
class Bicycle implements VehicleInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @param mixed $destination
|
||||||
|
*
|
||||||
|
* @return mixed|void
|
||||||
|
*/
|
||||||
public function driveTo($destination)
|
public function driveTo($destination)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\SimpleFactory;
|
namespace DesignPatterns\SimpleFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -17,7 +13,9 @@ namespace DesignPatterns\SimpleFactory;
|
|||||||
*/
|
*/
|
||||||
class ConcreteFactory
|
class ConcreteFactory
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
protected $typeList;
|
protected $typeList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,7 +34,8 @@ class ConcreteFactory
|
|||||||
* Creates a vehicle
|
* Creates a vehicle
|
||||||
*
|
*
|
||||||
* @param string $type a known type key
|
* @param string $type a known type key
|
||||||
* @return Vehicle a new instance of Vehicle
|
*
|
||||||
|
* @return VehicleInterface a new instance of VehicleInterface
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function createVehicle($type)
|
public function createVehicle($type)
|
||||||
@@ -48,5 +47,4 @@ class ConcreteFactory
|
|||||||
|
|
||||||
return new $className();
|
return new $className();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -1,20 +1,17 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\SimpleFactory;
|
namespace DesignPatterns\SimpleFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scooter is a Scooter
|
* Scooter is a Scooter
|
||||||
*/
|
*/
|
||||||
class Scooter implements Vehicle
|
class Scooter implements VehicleInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @param mixed $destination
|
||||||
|
*/
|
||||||
public function driveTo($destination)
|
public function driveTo($destination)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@@ -1,16 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* DesignPatternPHP
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DesignPatterns\SimpleFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Vehicle is a contract for a vehicle
|
|
||||||
*/
|
|
||||||
interface Vehicle
|
|
||||||
{
|
|
||||||
|
|
||||||
function driveTo($destination);
|
|
||||||
}
|
|
16
SimpleFactory/VehicleInterface.php
Normal file
16
SimpleFactory/VehicleInterface.php
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\SimpleFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VehicleInterface is a contract for a vehicle
|
||||||
|
*/
|
||||||
|
interface VehicleInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param mixed $destination
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function driveTo($destination);
|
||||||
|
}
|
@@ -40,7 +40,9 @@ class Singleton
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private function __construct()
|
private function __construct()
|
||||||
{}
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* prevent the instance from being cloned
|
* prevent the instance from being cloned
|
||||||
@@ -48,7 +50,9 @@ class Singleton
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function __clone()
|
private function __clone()
|
||||||
{}
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* prevent from being unserialized
|
* prevent from being unserialized
|
||||||
@@ -56,5 +60,7 @@ class Singleton
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function __wakeup()
|
private function __wakeup()
|
||||||
{}
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
49
State/CreateOrder.php
Normal file
49
State/CreateOrder.php
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CreateOrder
|
||||||
|
*/
|
||||||
|
class CreateOrder implements OrderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $order;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $order
|
||||||
|
*
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function __construct(array $order)
|
||||||
|
{
|
||||||
|
if (empty($order)) {
|
||||||
|
throw new \Exception('Order can not be empty!');
|
||||||
|
}
|
||||||
|
$this->order = $order;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function shipOrder()
|
||||||
|
{
|
||||||
|
$this->order['status'] = 'shipping';
|
||||||
|
$this->order['updatedTime'] = time();
|
||||||
|
|
||||||
|
// Setting the new order status into database;
|
||||||
|
return $this->updateOrder($order);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed|void
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function completeOrder()
|
||||||
|
{
|
||||||
|
//Can not complete the order which status is created, throw exception;
|
||||||
|
throw new \Exception('Can not complete the order which status is created!');
|
||||||
|
}
|
||||||
|
}
|
37
State/OrderController.php
Normal file
37
State/OrderController.php
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class OrderController
|
||||||
|
*/
|
||||||
|
class OrderController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
*/
|
||||||
|
public function shipAction($id)
|
||||||
|
{
|
||||||
|
$order = OrderFactory::getOrder($id);
|
||||||
|
try {
|
||||||
|
$order->shipOrder($id);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
//handle error!
|
||||||
|
}
|
||||||
|
// response to browser
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
*/
|
||||||
|
public function completeAction($id)
|
||||||
|
{
|
||||||
|
$order = OrderFactory::getOrder($id);
|
||||||
|
try {
|
||||||
|
$order->completeOrder($id);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
//handle error!
|
||||||
|
}
|
||||||
|
// response to browser
|
||||||
|
}
|
||||||
|
}
|
35
State/OrderFactory.php
Normal file
35
State/OrderFactory.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class OrderFactory
|
||||||
|
*/
|
||||||
|
class OrderFactory
|
||||||
|
{
|
||||||
|
private function __construct()
|
||||||
|
{
|
||||||
|
throw Exception('Can not instance the OrderFactory class!');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
*
|
||||||
|
* @return CreateOrder|ShippingOrder
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public static function getOrder($id)
|
||||||
|
{
|
||||||
|
$order = 'Get Order From Database';
|
||||||
|
|
||||||
|
switch ($order['status']) {
|
||||||
|
case 'created':
|
||||||
|
return new CreateOrder($order);
|
||||||
|
case 'shipping':
|
||||||
|
return new ShippingOrder($order);
|
||||||
|
default:
|
||||||
|
throw new \Exception('Order status error!');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user