Merged branch master into translate-template
@@ -3,38 +3,10 @@
|
||||
namespace DesignPatterns\Creational\AbstractFactory;
|
||||
|
||||
/**
|
||||
* class AbstractFactory.
|
||||
*
|
||||
* Sometimes also known as "Kit" in a GUI libraries.
|
||||
*
|
||||
* This design pattern implements the Dependency Inversion Principle since
|
||||
* it is the concrete subclass which creates concrete components.
|
||||
*
|
||||
* In this case, the abstract factory is a contract for creating some components
|
||||
* for the web. There are two components : Text and Picture. There are two ways
|
||||
* of rendering : HTML or JSON.
|
||||
*
|
||||
* Therefore 4 concrete classes, but the client just needs to know this contract
|
||||
* to build a correct HTTP response (for a HTML page or for an AJAX request).
|
||||
* for the web. There are two ways of rendering text: HTML and JSON
|
||||
*/
|
||||
abstract class AbstractFactory
|
||||
{
|
||||
/**
|
||||
* Creates a text component.
|
||||
*
|
||||
* @param string $content
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
abstract public function createText($content);
|
||||
|
||||
/**
|
||||
* Creates a picture component.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $name
|
||||
*
|
||||
* @return Picture
|
||||
*/
|
||||
abstract public function createPicture($path, $name = '');
|
||||
abstract public function createText(string $content): Text;
|
||||
}
|
||||
|
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\AbstractFactory\Html;
|
||||
|
||||
use DesignPatterns\Creational\AbstractFactory\Picture as BasePicture;
|
||||
|
||||
/**
|
||||
* Class Picture.
|
||||
*
|
||||
* Picture is a concrete image for HTML rendering
|
||||
*/
|
||||
class Picture extends BasePicture
|
||||
{
|
||||
/**
|
||||
* some crude rendering from HTML output.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return sprintf('<img src="%s" title="%s"/>', $this->path, $this->name);
|
||||
}
|
||||
}
|
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\AbstractFactory\Html;
|
||||
|
||||
use DesignPatterns\Creational\AbstractFactory\Text as BaseText;
|
||||
|
||||
/**
|
||||
* Class Text.
|
||||
*
|
||||
* Text is a concrete text for HTML rendering
|
||||
*/
|
||||
class Text extends BaseText
|
||||
{
|
||||
/**
|
||||
* some crude rendering from HTML output.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return '<div>'.htmlspecialchars($this->text).'</div>';
|
||||
}
|
||||
}
|
@@ -2,35 +2,10 @@
|
||||
|
||||
namespace DesignPatterns\Creational\AbstractFactory;
|
||||
|
||||
/**
|
||||
* Class HtmlFactory.
|
||||
*
|
||||
* HtmlFactory is a concrete factory for HTML component
|
||||
*/
|
||||
class HtmlFactory extends AbstractFactory
|
||||
{
|
||||
/**
|
||||
* Creates a picture component.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $name
|
||||
*
|
||||
* @return Html\Picture|Picture
|
||||
*/
|
||||
public function createPicture($path, $name = '')
|
||||
public function createText(string $content): Text
|
||||
{
|
||||
return new Html\Picture($path, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a text component.
|
||||
*
|
||||
* @param string $content
|
||||
*
|
||||
* @return Html\Text|Text
|
||||
*/
|
||||
public function createText($content)
|
||||
{
|
||||
return new Html\Text($content);
|
||||
return new HtmlText($content);
|
||||
}
|
||||
}
|
||||
|
8
Creational/AbstractFactory/HtmlText.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\AbstractFactory;
|
||||
|
||||
class HtmlText extends Text
|
||||
{
|
||||
// do something here
|
||||
}
|
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\AbstractFactory\Json;
|
||||
|
||||
use DesignPatterns\Creational\AbstractFactory\Picture as BasePicture;
|
||||
|
||||
/**
|
||||
* Class Picture.
|
||||
*
|
||||
* Picture is a concrete image for JSON rendering
|
||||
*/
|
||||
class Picture extends BasePicture
|
||||
{
|
||||
/**
|
||||
* some crude rendering from JSON output.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return json_encode(array('title' => $this->name, 'path' => $this->path));
|
||||
}
|
||||
}
|
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\AbstractFactory\Json;
|
||||
|
||||
use DesignPatterns\Creational\AbstractFactory\Text as BaseText;
|
||||
|
||||
/**
|
||||
* Class Text.
|
||||
*
|
||||
* Text is a text component with a JSON rendering
|
||||
*/
|
||||
class Text extends BaseText
|
||||
{
|
||||
/**
|
||||
* some crude rendering from JSON output.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return json_encode(array('content' => $this->text));
|
||||
}
|
||||
}
|
@@ -2,36 +2,10 @@
|
||||
|
||||
namespace DesignPatterns\Creational\AbstractFactory;
|
||||
|
||||
/**
|
||||
* Class JsonFactory.
|
||||
*
|
||||
* JsonFactory is a factory for creating a family of JSON component
|
||||
* (example for ajax)
|
||||
*/
|
||||
class JsonFactory extends AbstractFactory
|
||||
{
|
||||
/**
|
||||
* Creates a picture component.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $name
|
||||
*
|
||||
* @return Json\Picture|Picture
|
||||
*/
|
||||
public function createPicture($path, $name = '')
|
||||
public function createText(string $content): Text
|
||||
{
|
||||
return new Json\Picture($path, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a text component.
|
||||
*
|
||||
* @param string $content
|
||||
*
|
||||
* @return Json\Text|Text
|
||||
*/
|
||||
public function createText($content)
|
||||
{
|
||||
return new Json\Text($content);
|
||||
return new JsonText($content);
|
||||
}
|
||||
}
|
||||
|
8
Creational/AbstractFactory/JsonText.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\AbstractFactory;
|
||||
|
||||
class JsonText extends Text
|
||||
{
|
||||
// do something here
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\AbstractFactory;
|
||||
|
||||
/**
|
||||
* Interface MediaInterface.
|
||||
*
|
||||
* This contract is not part of the pattern, in general case, each component
|
||||
* are not related
|
||||
*/
|
||||
interface MediaInterface
|
||||
{
|
||||
/**
|
||||
* some crude rendering from JSON or html output (depended on concrete class).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function render();
|
||||
}
|
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\AbstractFactory;
|
||||
|
||||
/**
|
||||
* Class Picture.
|
||||
*/
|
||||
abstract class Picture implements MediaInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $path;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param string $name
|
||||
*/
|
||||
public function __construct($path, $name = '')
|
||||
{
|
||||
$this->name = (string) $name;
|
||||
$this->path = (string) $path;
|
||||
}
|
||||
}
|
@@ -39,45 +39,21 @@ HtmlFactory.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
MediaInterface.php
|
||||
|
||||
.. literalinclude:: MediaInterface.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
Picture.php
|
||||
|
||||
.. literalinclude:: Picture.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
Text.php
|
||||
|
||||
.. literalinclude:: Text.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
Json/Picture.php
|
||||
JsonText.php
|
||||
|
||||
.. literalinclude:: Json/Picture.php
|
||||
.. literalinclude:: JsonText.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
Json/Text.php
|
||||
HtmlText.php
|
||||
|
||||
.. literalinclude:: Json/Text.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
Html/Picture.php
|
||||
|
||||
.. literalinclude:: Html/Picture.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
Html/Text.php
|
||||
|
||||
.. literalinclude:: Html/Text.php
|
||||
.. literalinclude:: HtmlText.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
|
@@ -2,43 +2,24 @@
|
||||
|
||||
namespace DesignPatterns\Creational\AbstractFactory\Tests;
|
||||
|
||||
use DesignPatterns\Creational\AbstractFactory\AbstractFactory;
|
||||
use DesignPatterns\Creational\AbstractFactory\HtmlFactory;
|
||||
use DesignPatterns\Creational\AbstractFactory\JsonFactory;
|
||||
|
||||
/**
|
||||
* AbstractFactoryTest tests concrete factories.
|
||||
*/
|
||||
class AbstractFactoryTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function getFactories()
|
||||
public function testCanCreateHtmlText()
|
||||
{
|
||||
return array(
|
||||
array(new JsonFactory()),
|
||||
array(new HtmlFactory()),
|
||||
);
|
||||
$factory = new HtmlFactory();
|
||||
$text = $factory->createText('foobar');
|
||||
|
||||
$this->assertInstanceOf('DesignPatterns\Creational\AbstractFactory\HtmlText', $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the client of factories. Note that the client does not
|
||||
* care which factory is given to him, he can create any component he
|
||||
* wants and render how he wants.
|
||||
*
|
||||
* @dataProvider getFactories
|
||||
*/
|
||||
public function testComponentCreation(AbstractFactory $factory)
|
||||
public function testCanCreateJsonText()
|
||||
{
|
||||
$article = array(
|
||||
$factory->createText('Lorem Ipsum'),
|
||||
$factory->createPicture('/image.jpg', 'caption'),
|
||||
$factory->createText('footnotes'),
|
||||
);
|
||||
$factory = new JsonFactory();
|
||||
$text = $factory->createText('foobar');
|
||||
|
||||
$this->assertContainsOnly('DesignPatterns\Creational\AbstractFactory\MediaInterface', $article);
|
||||
|
||||
/* this is the time to look at the Builder pattern. This pattern
|
||||
* helps you to create complex object like that article above with
|
||||
* a given Abstract Factory
|
||||
*/
|
||||
$this->assertInstanceOf('DesignPatterns\Creational\AbstractFactory\JsonText', $text);
|
||||
}
|
||||
}
|
||||
|
@@ -2,21 +2,15 @@
|
||||
|
||||
namespace DesignPatterns\Creational\AbstractFactory;
|
||||
|
||||
/**
|
||||
* Class Text.
|
||||
*/
|
||||
abstract class Text implements MediaInterface
|
||||
abstract class Text
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $text;
|
||||
private $text;
|
||||
|
||||
/**
|
||||
* @param string $text
|
||||
*/
|
||||
public function __construct($text)
|
||||
public function __construct(string $text)
|
||||
{
|
||||
$this->text = (string) $text;
|
||||
$this->text = $text;
|
||||
}
|
||||
}
|
||||
|
@@ -1,38 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Diagram>
|
||||
<ID>PHP</ID>
|
||||
<OriginalElement>\DesignPatterns\Creational\AbstractFactory\AbstractFactory</OriginalElement>
|
||||
<nodes>
|
||||
<node x="281.0" y="228.0">\DesignPatterns\Creational\AbstractFactory\Html\Text</node>
|
||||
<node x="150.0" y="229.0">\DesignPatterns\Creational\AbstractFactory\Html\Picture</node>
|
||||
<node x="223.0" y="117.0">\DesignPatterns\Creational\AbstractFactory\HtmlFactory</node>
|
||||
<node x="0.0" y="117.0">\DesignPatterns\Creational\AbstractFactory\JsonFactory</node>
|
||||
<node x="126.0" y="0.0">\DesignPatterns\Creational\AbstractFactory\AbstractFactory</node>
|
||||
<node x="0.0" y="229.0">\DesignPatterns\Creational\AbstractFactory\MediaInterface</node>
|
||||
</nodes>
|
||||
<notes />
|
||||
<edges>
|
||||
<edge source="\DesignPatterns\Creational\AbstractFactory\HtmlFactory" target="\DesignPatterns\Creational\AbstractFactory\AbstractFactory">
|
||||
<point x="0.0" y="-33.5" />
|
||||
<point x="324.5" y="92.0" />
|
||||
<point x="256.5" y="92.0" />
|
||||
<point x="43.5" y="33.5" />
|
||||
</edge>
|
||||
<edge source="\DesignPatterns\Creational\AbstractFactory\JsonFactory" target="\DesignPatterns\Creational\AbstractFactory\AbstractFactory">
|
||||
<point x="0.0" y="-33.5" />
|
||||
<point x="101.5" y="92.0" />
|
||||
<point x="169.5" y="92.0" />
|
||||
<point x="-43.5" y="33.5" />
|
||||
</edge>
|
||||
</edges>
|
||||
<settings layout="Hierarchic Group" zoom="1.0" x="213.0" y="138.0" />
|
||||
<SelectedNodes />
|
||||
<Categories>
|
||||
<Category>Fields</Category>
|
||||
<Category>Constants</Category>
|
||||
<Category>Constructors</Category>
|
||||
<Category>Methods</Category>
|
||||
</Categories>
|
||||
<VISIBILITY>private</VISIBILITY>
|
||||
</Diagram>
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Diagram>
|
||||
<ID>PHP</ID>
|
||||
<OriginalElement>\DesignPatterns\Creational\AbstractFactory\AbstractFactory</OriginalElement>
|
||||
<nodes>
|
||||
<node x="214.0" y="101.0">\DesignPatterns\Creational\AbstractFactory\JsonFactory</node>
|
||||
<node x="107.0" y="0.0">\DesignPatterns\Creational\AbstractFactory\AbstractFactory</node>
|
||||
<node x="0.0" y="101.0">\DesignPatterns\Creational\AbstractFactory\HtmlFactory</node>
|
||||
<node x="111.0" y="298.0">\DesignPatterns\Creational\AbstractFactory\JsonText</node>
|
||||
<node x="0.0" y="298.0">\DesignPatterns\Creational\AbstractFactory\HtmlText</node>
|
||||
<node x="51.5" y="197.0">\DesignPatterns\Creational\AbstractFactory\Text</node>
|
||||
</nodes>
|
||||
<notes />
|
||||
<edges>
|
||||
<edge source="\DesignPatterns\Creational\AbstractFactory\HtmlText" target="\DesignPatterns\Creational\AbstractFactory\Text">
|
||||
<point x="0.0" y="-14.5" />
|
||||
<point x="45.5" y="273.0" />
|
||||
<point x="75.75" y="273.0" />
|
||||
<point x="-24.25" y="25.5" />
|
||||
</edge>
|
||||
<edge source="\DesignPatterns\Creational\AbstractFactory\JsonText" target="\DesignPatterns\Creational\AbstractFactory\Text">
|
||||
<point x="0.0" y="-14.5" />
|
||||
<point x="154.5" y="273.0" />
|
||||
<point x="124.25" y="273.0" />
|
||||
<point x="24.25" y="25.5" />
|
||||
</edge>
|
||||
<edge source="\DesignPatterns\Creational\AbstractFactory\JsonFactory" target="\DesignPatterns\Creational\AbstractFactory\AbstractFactory">
|
||||
<point x="0.0" y="-25.5" />
|
||||
<point x="311.0" y="76.0" />
|
||||
<point x="252.5" y="76.0" />
|
||||
<point x="48.5" y="25.5" />
|
||||
</edge>
|
||||
<edge source="\DesignPatterns\Creational\AbstractFactory\HtmlFactory" target="\DesignPatterns\Creational\AbstractFactory\AbstractFactory">
|
||||
<point x="0.0" y="-25.5" />
|
||||
<point x="97.0" y="76.0" />
|
||||
<point x="155.5" y="76.0" />
|
||||
<point x="-48.5" y="25.5" />
|
||||
</edge>
|
||||
</edges>
|
||||
<settings layout="Hierarchic Group" zoom="1.0" x="117.0" y="130.5" />
|
||||
<SelectedNodes>
|
||||
<node>\DesignPatterns\Creational\AbstractFactory\AbstractFactory</node>
|
||||
</SelectedNodes>
|
||||
<Categories>
|
||||
<Category>Methods</Category>
|
||||
<Category>Constants</Category>
|
||||
<Category>Fields</Category>
|
||||
</Categories>
|
||||
<VISIBILITY>private</VISIBILITY>
|
||||
</Diagram>
|
||||
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 90 KiB |
@@ -1,54 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\Builder;
|
||||
|
||||
/**
|
||||
* BikeBuilder builds bike.
|
||||
*/
|
||||
class BikeBuilder implements BuilderInterface
|
||||
{
|
||||
/**
|
||||
* @var Parts\Bike
|
||||
*/
|
||||
protected $bike;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addDoors()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addEngine()
|
||||
{
|
||||
$this->bike->setPart('engine', new Parts\Engine());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addWheel()
|
||||
{
|
||||
$this->bike->setPart('forwardWheel', new Parts\Wheel());
|
||||
$this->bike->setPart('rearWheel', new Parts\Wheel());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createVehicle()
|
||||
{
|
||||
$this->bike = new Parts\Bike();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getVehicle()
|
||||
{
|
||||
return $this->bike;
|
||||
}
|
||||
}
|
@@ -2,30 +2,17 @@
|
||||
|
||||
namespace DesignPatterns\Creational\Builder;
|
||||
|
||||
use DesignPatterns\Creational\Builder\Parts\Vehicle;
|
||||
|
||||
interface BuilderInterface
|
||||
{
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function createVehicle();
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function addWheel();
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function addEngine();
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function addDoors();
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getVehicle();
|
||||
public function getVehicle(): Vehicle;
|
||||
}
|
||||
|
@@ -2,36 +2,27 @@
|
||||
|
||||
namespace DesignPatterns\Creational\Builder;
|
||||
|
||||
/**
|
||||
* CarBuilder builds car.
|
||||
*/
|
||||
use DesignPatterns\Creational\Builder\Parts\Vehicle;
|
||||
|
||||
class CarBuilder implements BuilderInterface
|
||||
{
|
||||
/**
|
||||
* @var Parts\Car
|
||||
*/
|
||||
protected $car;
|
||||
private $car;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
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('trunkLid', new Parts\Door());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function addEngine()
|
||||
{
|
||||
$this->car->setPart('engine', new Parts\Engine());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function addWheel()
|
||||
{
|
||||
$this->car->setPart('wheelLF', new Parts\Wheel());
|
||||
@@ -40,18 +31,12 @@ class CarBuilder implements BuilderInterface
|
||||
$this->car->setPart('wheelRR', new Parts\Wheel());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function createVehicle()
|
||||
{
|
||||
$this->car = new Parts\Car();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Parts\Car
|
||||
*/
|
||||
public function getVehicle()
|
||||
public function getVehicle(): Vehicle
|
||||
{
|
||||
return $this->car;
|
||||
}
|
||||
|
@@ -2,22 +2,17 @@
|
||||
|
||||
namespace DesignPatterns\Creational\Builder;
|
||||
|
||||
use DesignPatterns\Creational\Builder\Parts\Vehicle;
|
||||
|
||||
/**
|
||||
* Director is part of the builder pattern. It knows the interface of the builder
|
||||
* and builds a complex object with the help of the builder.
|
||||
* and builds a complex object with the help of the builder
|
||||
*
|
||||
* You can also inject many builders instead of one to build more complex objects
|
||||
*/
|
||||
class Director
|
||||
{
|
||||
/**
|
||||
* The director don't know about concrete part.
|
||||
*
|
||||
* @param BuilderInterface $builder
|
||||
*
|
||||
* @return Parts\Vehicle
|
||||
*/
|
||||
public function build(BuilderInterface $builder)
|
||||
public function build(BuilderInterface $builder): Vehicle
|
||||
{
|
||||
$builder->createVehicle();
|
||||
$builder->addDoors();
|
||||
|
@@ -2,9 +2,6 @@
|
||||
|
||||
namespace DesignPatterns\Creational\Builder\Parts;
|
||||
|
||||
/**
|
||||
* Car is a car.
|
||||
*/
|
||||
class Car extends Vehicle
|
||||
{
|
||||
}
|
||||
|
@@ -2,9 +2,6 @@
|
||||
|
||||
namespace DesignPatterns\Creational\Builder\Parts;
|
||||
|
||||
/**
|
||||
* Class Door.
|
||||
*/
|
||||
class Door
|
||||
{
|
||||
}
|
||||
|
@@ -2,9 +2,6 @@
|
||||
|
||||
namespace DesignPatterns\Creational\Builder\Parts;
|
||||
|
||||
/**
|
||||
* Class Engine.
|
||||
*/
|
||||
class Engine
|
||||
{
|
||||
}
|
||||
|
@@ -2,9 +2,6 @@
|
||||
|
||||
namespace DesignPatterns\Creational\Builder\Parts;
|
||||
|
||||
/**
|
||||
* Bike is a bike.
|
||||
*/
|
||||
class Bike extends Vehicle
|
||||
class Truck extends Vehicle
|
||||
{
|
||||
}
|
@@ -2,19 +2,16 @@
|
||||
|
||||
namespace DesignPatterns\Creational\Builder\Parts;
|
||||
|
||||
/**
|
||||
* Vehicle class is an abstraction for a vehicle.
|
||||
*/
|
||||
abstract class Vehicle
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
* @var object[]
|
||||
*/
|
||||
protected $data;
|
||||
private $data = [];
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param object $value
|
||||
*/
|
||||
public function setPart($key, $value)
|
||||
{
|
||||
|
@@ -2,9 +2,6 @@
|
||||
|
||||
namespace DesignPatterns\Creational\Builder\Parts;
|
||||
|
||||
/**
|
||||
* Class Wheel.
|
||||
*/
|
||||
class Wheel
|
||||
{
|
||||
}
|
||||
|
@@ -44,9 +44,9 @@ BuilderInterface.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
BikeBuilder.php
|
||||
TruckBuilder.php
|
||||
|
||||
.. literalinclude:: BikeBuilder.php
|
||||
.. literalinclude:: TruckBuilder.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
@@ -62,9 +62,9 @@ Parts/Vehicle.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
Parts/Bike.php
|
||||
Parts/Truck.php
|
||||
|
||||
.. literalinclude:: Parts/Bike.php
|
||||
.. literalinclude:: Parts/Truck.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
|
@@ -2,40 +2,25 @@
|
||||
|
||||
namespace DesignPatterns\Creational\Builder\Tests;
|
||||
|
||||
use DesignPatterns\Creational\Builder\BikeBuilder;
|
||||
use DesignPatterns\Creational\Builder\BuilderInterface;
|
||||
use DesignPatterns\Creational\Builder\TruckBuilder;
|
||||
use DesignPatterns\Creational\Builder\CarBuilder;
|
||||
use DesignPatterns\Creational\Builder\Director;
|
||||
|
||||
/**
|
||||
* DirectorTest tests the builder pattern.
|
||||
*/
|
||||
class DirectorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $director;
|
||||
|
||||
protected function setUp()
|
||||
public function testCanBuildBike()
|
||||
{
|
||||
$this->director = new Director();
|
||||
$bikeBuilder = new TruckBuilder();
|
||||
$newVehicle = (new Director())->build($bikeBuilder);
|
||||
|
||||
$this->assertInstanceOf('DesignPatterns\Creational\Builder\Parts\Truck', $newVehicle);
|
||||
}
|
||||
|
||||
public function getBuilder()
|
||||
public function testCanBuildCar()
|
||||
{
|
||||
return array(
|
||||
array(new CarBuilder()),
|
||||
array(new BikeBuilder()),
|
||||
);
|
||||
}
|
||||
$carBuilder = new CarBuilder();
|
||||
$newVehicle = (new Director())->build($carBuilder);
|
||||
|
||||
/**
|
||||
* Here we test the build process. Notice that the client don't know
|
||||
* anything about the concrete builder.
|
||||
*
|
||||
* @dataProvider getBuilder
|
||||
*/
|
||||
public function testBuild(BuilderInterface $builder)
|
||||
{
|
||||
$newVehicle = $this->director->build($builder);
|
||||
$this->assertInstanceOf('DesignPatterns\Creational\Builder\Parts\Vehicle', $newVehicle);
|
||||
$this->assertInstanceOf('DesignPatterns\Creational\Builder\Parts\Car', $newVehicle);
|
||||
}
|
||||
}
|
||||
|
44
Creational/Builder/TruckBuilder.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\Builder;
|
||||
|
||||
use DesignPatterns\Creational\Builder\Parts\Vehicle;
|
||||
|
||||
class TruckBuilder implements BuilderInterface
|
||||
{
|
||||
/**
|
||||
* @var Parts\Truck
|
||||
*/
|
||||
private $truck;
|
||||
|
||||
public function addDoors()
|
||||
{
|
||||
$this->truck->setPart('rightDoor', new Parts\Door());
|
||||
$this->truck->setPart('leftDoor', new Parts\Door());
|
||||
}
|
||||
|
||||
public function addEngine()
|
||||
{
|
||||
$this->truck->setPart('truckEngine', new Parts\Engine());
|
||||
}
|
||||
|
||||
public function addWheel()
|
||||
{
|
||||
$this->truck->setPart('wheel1', new Parts\Wheel());
|
||||
$this->truck->setPart('wheel2', new Parts\Wheel());
|
||||
$this->truck->setPart('wheel3', new Parts\Wheel());
|
||||
$this->truck->setPart('wheel4', new Parts\Wheel());
|
||||
$this->truck->setPart('wheel5', new Parts\Wheel());
|
||||
$this->truck->setPart('wheel6', new Parts\Wheel());
|
||||
}
|
||||
|
||||
public function createVehicle()
|
||||
{
|
||||
$this->truck = new Parts\Truck();
|
||||
}
|
||||
|
||||
public function getVehicle(): Vehicle
|
||||
{
|
||||
return $this->truck;
|
||||
}
|
||||
}
|
@@ -2,22 +2,14 @@
|
||||
|
||||
namespace DesignPatterns\Creational\FactoryMethod;
|
||||
|
||||
/**
|
||||
* Bicycle is a bicycle.
|
||||
*/
|
||||
class Bicycle implements VehicleInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $color;
|
||||
private $color;
|
||||
|
||||
/**
|
||||
* Sets the color of the bicycle.
|
||||
*
|
||||
* @param string $rgb
|
||||
*/
|
||||
public function setColor($rgb)
|
||||
public function setColor(string $rgb)
|
||||
{
|
||||
$this->color = $rgb;
|
||||
}
|
||||
|
16
Creational/FactoryMethod/CarFerrari.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\FactoryMethod;
|
||||
|
||||
class CarFerrari implements VehicleInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $color;
|
||||
|
||||
public function setColor(string $rgb)
|
||||
{
|
||||
$this->color = $rgb;
|
||||
}
|
||||
}
|
21
Creational/FactoryMethod/CarMercedes.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\FactoryMethod;
|
||||
|
||||
class CarMercedes implements VehicleInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $color;
|
||||
|
||||
public function setColor(string $rgb)
|
||||
{
|
||||
$this->color = $rgb;
|
||||
}
|
||||
|
||||
public function addAMGTuning()
|
||||
{
|
||||
// do additional tuning here
|
||||
}
|
||||
}
|
@@ -2,36 +2,17 @@
|
||||
|
||||
namespace DesignPatterns\Creational\FactoryMethod;
|
||||
|
||||
/**
|
||||
* class FactoryMethod.
|
||||
*/
|
||||
abstract class FactoryMethod
|
||||
{
|
||||
const CHEAP = 1;
|
||||
const FAST = 2;
|
||||
const CHEAP = 'cheap';
|
||||
const FAST = 'fast';
|
||||
|
||||
/**
|
||||
* The children of the class must implement this method.
|
||||
*
|
||||
* Sometimes this method can be public to get "raw" object
|
||||
*
|
||||
* @param string $type a generic type
|
||||
*
|
||||
* @return VehicleInterface a new vehicle
|
||||
*/
|
||||
abstract protected function createVehicle($type);
|
||||
abstract protected function createVehicle(string $type): VehicleInterface;
|
||||
|
||||
/**
|
||||
* Creates a new vehicle.
|
||||
*
|
||||
* @param int $type
|
||||
*
|
||||
* @return VehicleInterface a new vehicle
|
||||
*/
|
||||
public function create($type)
|
||||
public function create(string $type): VehicleInterface
|
||||
{
|
||||
$obj = $this->createVehicle($type);
|
||||
$obj->setColor('#f00');
|
||||
$obj->setColor('black');
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\FactoryMethod;
|
||||
|
||||
/**
|
||||
* Ferrari is a italian car.
|
||||
*/
|
||||
class Ferrari implements VehicleInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $color;
|
||||
|
||||
/**
|
||||
* @param string $rgb
|
||||
*/
|
||||
public function setColor($rgb)
|
||||
{
|
||||
$this->color = $rgb;
|
||||
}
|
||||
}
|
@@ -2,28 +2,19 @@
|
||||
|
||||
namespace DesignPatterns\Creational\FactoryMethod;
|
||||
|
||||
/**
|
||||
* GermanFactory is a vehicle factory in Germany.
|
||||
*/
|
||||
class GermanFactory extends FactoryMethod
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createVehicle($type)
|
||||
protected function createVehicle(string $type): VehicleInterface
|
||||
{
|
||||
switch ($type) {
|
||||
case parent::CHEAP:
|
||||
return new Bicycle();
|
||||
break;
|
||||
case parent::FAST:
|
||||
$obj = new Porsche();
|
||||
// we can specialize the way we want some concrete Vehicle since
|
||||
// we know the class
|
||||
$obj->addTuningAMG();
|
||||
$carMercedes = new CarMercedes();
|
||||
// we can specialize the way we want some concrete Vehicle since we know the class
|
||||
$carMercedes->addAMGTuning();
|
||||
|
||||
return $obj;
|
||||
break;
|
||||
return $carMercedes;
|
||||
default:
|
||||
throw new \InvalidArgumentException("$type is not a valid vehicle");
|
||||
}
|
||||
|
@@ -2,23 +2,15 @@
|
||||
|
||||
namespace DesignPatterns\Creational\FactoryMethod;
|
||||
|
||||
/**
|
||||
* ItalianFactory is vehicle factory in Italy.
|
||||
*/
|
||||
class ItalianFactory extends FactoryMethod
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createVehicle($type)
|
||||
protected function createVehicle(string $type): VehicleInterface
|
||||
{
|
||||
switch ($type) {
|
||||
case parent::CHEAP:
|
||||
return new Bicycle();
|
||||
break;
|
||||
case parent::FAST:
|
||||
return new Ferrari();
|
||||
break;
|
||||
return new CarFerrari();
|
||||
default:
|
||||
throw new \InvalidArgumentException("$type is not a valid vehicle");
|
||||
}
|
||||
|
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\FactoryMethod;
|
||||
|
||||
/**
|
||||
* Porsche is a german car.
|
||||
*/
|
||||
class Porsche implements VehicleInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $color;
|
||||
|
||||
/**
|
||||
* @param string $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()
|
||||
{
|
||||
}
|
||||
}
|
@@ -52,23 +52,23 @@ VehicleInterface.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
Porsche.php
|
||||
CarMercedes.php
|
||||
|
||||
.. literalinclude:: Porsche.php
|
||||
.. literalinclude:: CarMercedes.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
Bicycle.php
|
||||
CarFerrari.php
|
||||
|
||||
.. literalinclude:: CarFerrari.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
Bicycle.php
|
||||
|
||||
.. literalinclude:: Bicycle.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
Ferrari.php
|
||||
|
||||
.. literalinclude:: Ferrari.php
|
||||
:language: php
|
||||
:linenos:
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
Test
|
||||
----
|
||||
|
@@ -6,44 +6,46 @@ use DesignPatterns\Creational\FactoryMethod\FactoryMethod;
|
||||
use DesignPatterns\Creational\FactoryMethod\GermanFactory;
|
||||
use DesignPatterns\Creational\FactoryMethod\ItalianFactory;
|
||||
|
||||
/**
|
||||
* FactoryMethodTest tests the factory method pattern.
|
||||
*/
|
||||
class FactoryMethodTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $type = array(
|
||||
FactoryMethod::CHEAP,
|
||||
FactoryMethod::FAST,
|
||||
);
|
||||
|
||||
public function getShop()
|
||||
public function testCanCreateCheapVehicleInGermany()
|
||||
{
|
||||
return array(
|
||||
array(new GermanFactory()),
|
||||
array(new ItalianFactory()),
|
||||
);
|
||||
$factory = new GermanFactory();
|
||||
$result = $factory->create(FactoryMethod::CHEAP);
|
||||
|
||||
$this->assertInstanceOf('DesignPatterns\Creational\FactoryMethod\Bicycle', $result);
|
||||
}
|
||||
|
||||
public function testCanCreateFastVehicleInGermany()
|
||||
{
|
||||
$factory = new GermanFactory();
|
||||
$result = $factory->create(FactoryMethod::FAST);
|
||||
|
||||
$this->assertInstanceOf('DesignPatterns\Creational\FactoryMethod\CarMercedes', $result);
|
||||
}
|
||||
|
||||
public function testCanCreateCheapVehicleInItaly()
|
||||
{
|
||||
$factory = new ItalianFactory();
|
||||
$result = $factory->create(FactoryMethod::CHEAP);
|
||||
|
||||
$this->assertInstanceOf('DesignPatterns\Creational\FactoryMethod\Bicycle', $result);
|
||||
}
|
||||
|
||||
public function testCanCreateFastVehicleInItaly()
|
||||
{
|
||||
$factory = new ItalianFactory();
|
||||
$result = $factory->create(FactoryMethod::FAST);
|
||||
|
||||
$this->assertInstanceOf('DesignPatterns\Creational\FactoryMethod\CarFerrari', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getShop
|
||||
*/
|
||||
public function testCreation(FactoryMethod $shop)
|
||||
{
|
||||
// this test method acts as a client for the factory. We don't care
|
||||
// about the factory, all we know is it can produce vehicle
|
||||
foreach ($this->type as $oneType) {
|
||||
$vehicle = $shop->create($oneType);
|
||||
$this->assertInstanceOf('DesignPatterns\Creational\FactoryMethod\VehicleInterface', $vehicle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getShop
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessage spaceship is not a valid vehicle
|
||||
*/
|
||||
public function testUnknownType(FactoryMethod $shop)
|
||||
public function testUnknownType()
|
||||
{
|
||||
$shop->create('spaceship');
|
||||
(new ItalianFactory())->create('spaceship');
|
||||
}
|
||||
}
|
||||
|
@@ -2,15 +2,7 @@
|
||||
|
||||
namespace DesignPatterns\Creational\FactoryMethod;
|
||||
|
||||
/**
|
||||
* VehicleInterface is a contract for a vehicle.
|
||||
*/
|
||||
interface VehicleInterface
|
||||
{
|
||||
/**
|
||||
* sets the color of the vehicle.
|
||||
*
|
||||
* @param string $rgb
|
||||
*/
|
||||
public function setColor($rgb);
|
||||
public function setColor(string $rgb);
|
||||
}
|
||||
|
@@ -2,46 +2,26 @@
|
||||
|
||||
namespace DesignPatterns\Creational\Multiton;
|
||||
|
||||
/**
|
||||
* class Multiton.
|
||||
*/
|
||||
class Multiton
|
||||
{
|
||||
/**
|
||||
* the first instance.
|
||||
*/
|
||||
const INSTANCE_1 = '1';
|
||||
|
||||
/**
|
||||
* the second instance.
|
||||
*/
|
||||
const INSTANCE_2 = '2';
|
||||
|
||||
/**
|
||||
* holds the named instances.
|
||||
*
|
||||
* @var array
|
||||
* @var Multiton[]
|
||||
*/
|
||||
private static $instances = array();
|
||||
private static $instances = [];
|
||||
|
||||
/**
|
||||
* should not be called from outside: private!
|
||||
* this is private to prevent from creating arbitrary instances
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the instance with the given name, e.g. Multiton::INSTANCE_1
|
||||
* uses lazy initialization.
|
||||
*
|
||||
* @param string $instanceName
|
||||
*
|
||||
* @return Multiton
|
||||
*/
|
||||
public static function getInstance($instanceName)
|
||||
public static function getInstance(string $instanceName): Multiton
|
||||
{
|
||||
if (!array_key_exists($instanceName, self::$instances)) {
|
||||
if (!isset(self::$instances[$instanceName])) {
|
||||
self::$instances[$instanceName] = new self();
|
||||
}
|
||||
|
||||
@@ -49,18 +29,14 @@ class Multiton
|
||||
}
|
||||
|
||||
/**
|
||||
* prevent instance from being cloned.
|
||||
*
|
||||
* @return void
|
||||
* prevent instance from being cloned
|
||||
*/
|
||||
private function __clone()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* prevent instance from being unserialized.
|
||||
*
|
||||
* @return void
|
||||
* prevent instance from being unserialized
|
||||
*/
|
||||
private function __wakeup()
|
||||
{
|
||||
|
27
Creational/Multiton/Tests/MultitonTest.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\Singleton\Tests;
|
||||
|
||||
use DesignPatterns\Creational\Multiton\Multiton;
|
||||
|
||||
class MultitonTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testUniqueness()
|
||||
{
|
||||
$firstCall = Multiton::getInstance(Multiton::INSTANCE_1);
|
||||
$secondCall = Multiton::getInstance(Multiton::INSTANCE_1);
|
||||
|
||||
$this->assertInstanceOf('DesignPatterns\Creational\Multiton\Multiton', $firstCall);
|
||||
$this->assertSame($firstCall, $secondCall);
|
||||
}
|
||||
|
||||
public function testUniquenessForEveryInstance()
|
||||
{
|
||||
$firstCall = Multiton::getInstance(Multiton::INSTANCE_1);
|
||||
$secondCall = Multiton::getInstance(Multiton::INSTANCE_2);
|
||||
|
||||
$this->assertInstanceOf('DesignPatterns\Creational\Multiton\Multiton', $firstCall);
|
||||
$this->assertInstanceOf('DesignPatterns\Creational\Multiton\Multiton', $secondCall);
|
||||
$this->assertNotSame($firstCall, $secondCall);
|
||||
}
|
||||
}
|
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\Pool;
|
||||
|
||||
class Pool
|
||||
{
|
||||
private $instances = array();
|
||||
private $class;
|
||||
|
||||
public function __construct($class)
|
||||
{
|
||||
$this->class = $class;
|
||||
}
|
||||
|
||||
public function get()
|
||||
{
|
||||
if (count($this->instances) > 0) {
|
||||
return array_pop($this->instances);
|
||||
}
|
||||
|
||||
return new $this->class();
|
||||
}
|
||||
|
||||
public function dispose($instance)
|
||||
{
|
||||
$this->instances[] = $instance;
|
||||
}
|
||||
}
|
@@ -1,51 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\Pool;
|
||||
|
||||
class Processor
|
||||
{
|
||||
private $pool;
|
||||
private $processing = 0;
|
||||
private $maxProcesses = 3;
|
||||
private $waitingQueue = array();
|
||||
|
||||
public function __construct(Pool $pool)
|
||||
{
|
||||
$this->pool = $pool;
|
||||
}
|
||||
|
||||
public function process($image)
|
||||
{
|
||||
if ($this->processing++ < $this->maxProcesses) {
|
||||
$this->createWorker($image);
|
||||
} else {
|
||||
$this->pushToWaitingQueue($image);
|
||||
}
|
||||
}
|
||||
|
||||
private function createWorker($image)
|
||||
{
|
||||
$worker = $this->pool->get();
|
||||
$worker->run($image, array($this, 'processDone'));
|
||||
}
|
||||
|
||||
public function processDone($worker)
|
||||
{
|
||||
$this->processing--;
|
||||
$this->pool->dispose($worker);
|
||||
|
||||
if (count($this->waitingQueue) > 0) {
|
||||
$this->createWorker($this->popFromWaitingQueue());
|
||||
}
|
||||
}
|
||||
|
||||
private function pushToWaitingQueue($image)
|
||||
{
|
||||
$this->waitingQueue[] = $image;
|
||||
}
|
||||
|
||||
private function popFromWaitingQueue()
|
||||
{
|
||||
return array_pop($this->waitingQueue);
|
||||
}
|
||||
}
|
@@ -36,21 +36,15 @@ Code
|
||||
|
||||
You can also find these code on `GitHub`_
|
||||
|
||||
Pool.php
|
||||
WorkerPool.php
|
||||
|
||||
.. literalinclude:: Pool.php
|
||||
.. literalinclude:: WorkerPool.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
Processor.php
|
||||
StringReverseWorker.php
|
||||
|
||||
.. literalinclude:: Processor.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
Worker.php
|
||||
|
||||
.. literalinclude:: Worker.php
|
||||
.. literalinclude:: StringReverseWorker.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
@@ -63,11 +57,5 @@ Tests/PoolTest.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
Tests/TestWorker.php
|
||||
|
||||
.. literalinclude:: Tests/TestWorker.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Creational/Pool
|
||||
.. __: http://en.wikipedia.org/wiki/Object_pool_pattern
|
||||
|
21
Creational/Pool/StringReverseWorker.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\Pool;
|
||||
|
||||
class StringReverseWorker
|
||||
{
|
||||
/**
|
||||
* @var \DateTime
|
||||
*/
|
||||
private $createdAt;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->createdAt = new \DateTime();
|
||||
}
|
||||
|
||||
public function run(string $text)
|
||||
{
|
||||
return strrev($text);
|
||||
}
|
||||
}
|
@@ -2,21 +2,28 @@
|
||||
|
||||
namespace DesignPatterns\Creational\Pool\Tests;
|
||||
|
||||
use DesignPatterns\Creational\Pool\Pool;
|
||||
use DesignPatterns\Creational\Pool\WorkerPool;
|
||||
|
||||
class PoolTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testPool()
|
||||
public function testCanGetNewInstancesWithGet()
|
||||
{
|
||||
$pool = new Pool('DesignPatterns\Creational\Pool\Tests\TestWorker');
|
||||
$worker = $pool->get();
|
||||
$pool = new WorkerPool();
|
||||
$worker1 = $pool->get();
|
||||
$worker2 = $pool->get();
|
||||
|
||||
$this->assertEquals(1, $worker->id);
|
||||
$this->assertCount(2, $pool);
|
||||
$this->assertNotSame($worker1, $worker2);
|
||||
}
|
||||
|
||||
$worker->id = 5;
|
||||
$pool->dispose($worker);
|
||||
public function testCanGetSameInstanceTwiceWhenDisposingItFirst()
|
||||
{
|
||||
$pool = new WorkerPool();
|
||||
$worker1 = $pool->get();
|
||||
$pool->dispose($worker1);
|
||||
$worker2 = $pool->get();
|
||||
|
||||
$this->assertEquals(5, $pool->get()->id);
|
||||
$this->assertEquals(1, $pool->get()->id);
|
||||
$this->assertCount(1, $pool);
|
||||
$this->assertSame($worker1, $worker2);
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\Pool\Tests;
|
||||
|
||||
class TestWorker
|
||||
{
|
||||
public $id = 1;
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\Pool;
|
||||
|
||||
class Worker
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
// let's say that constuctor does really expensive work...
|
||||
// for example creates "thread"
|
||||
}
|
||||
|
||||
public function run($image, array $callback)
|
||||
{
|
||||
// do something with $image...
|
||||
// and when it's done, execute callback
|
||||
call_user_func($callback, $this);
|
||||
}
|
||||
}
|
44
Creational/Pool/WorkerPool.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\Pool;
|
||||
|
||||
class WorkerPool implements \Countable
|
||||
{
|
||||
/**
|
||||
* @var StringReverseWorker[]
|
||||
*/
|
||||
private $occupiedWorkers = [];
|
||||
|
||||
/**
|
||||
* @var StringReverseWorker[]
|
||||
*/
|
||||
private $freeWorkers = [];
|
||||
|
||||
public function get(): StringReverseWorker
|
||||
{
|
||||
if (count($this->freeWorkers) == 0) {
|
||||
$worker = new StringReverseWorker();
|
||||
} else {
|
||||
$worker = array_pop($this->freeWorkers);
|
||||
}
|
||||
|
||||
$this->occupiedWorkers[spl_object_hash($worker)] = $worker;
|
||||
|
||||
return $worker;
|
||||
}
|
||||
|
||||
public function dispose(StringReverseWorker $worker)
|
||||
{
|
||||
$key = spl_object_hash($worker);
|
||||
|
||||
if (isset($this->occupiedWorkers[$key])) {
|
||||
unset($this->occupiedWorkers[$key]);
|
||||
$this->freeWorkers[$key] = $worker;
|
||||
}
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->occupiedWorkers) + count($this->freeWorkers);
|
||||
}
|
||||
}
|
@@ -2,9 +2,6 @@
|
||||
|
||||
namespace DesignPatterns\Creational\Prototype;
|
||||
|
||||
/**
|
||||
* Class BarBookPrototype.
|
||||
*/
|
||||
class BarBookPrototype extends BookPrototype
|
||||
{
|
||||
/**
|
||||
@@ -12,9 +9,6 @@ class BarBookPrototype extends BookPrototype
|
||||
*/
|
||||
protected $category = 'Bar';
|
||||
|
||||
/**
|
||||
* empty clone.
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
}
|
||||
|
@@ -2,9 +2,6 @@
|
||||
|
||||
namespace DesignPatterns\Creational\Prototype;
|
||||
|
||||
/**
|
||||
* class BookPrototype.
|
||||
*/
|
||||
abstract class BookPrototype
|
||||
{
|
||||
/**
|
||||
@@ -17,24 +14,13 @@ abstract class BookPrototype
|
||||
*/
|
||||
protected $category;
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract public function __clone();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle()
|
||||
public function getTitle(): string
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $title
|
||||
*/
|
||||
public function setTitle($title)
|
||||
{
|
||||
$this->title = $title;
|
||||
|
@@ -2,16 +2,13 @@
|
||||
|
||||
namespace DesignPatterns\Creational\Prototype;
|
||||
|
||||
/**
|
||||
* Class FooBookPrototype.
|
||||
*/
|
||||
class FooBookPrototype extends BookPrototype
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $category = 'Foo';
|
||||
|
||||
/**
|
||||
* empty clone.
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
}
|
||||
|
@@ -25,12 +25,6 @@ Code
|
||||
|
||||
You can also find these code on `GitHub`_
|
||||
|
||||
index.php
|
||||
|
||||
.. literalinclude:: index.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
BookPrototype.php
|
||||
|
||||
.. literalinclude:: BookPrototype.php
|
||||
@@ -52,5 +46,11 @@ FooBookPrototype.php
|
||||
Test
|
||||
----
|
||||
|
||||
Tests/PrototypeTest.php
|
||||
|
||||
.. literalinclude:: Tests/PrototypeTest.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Creational/Prototype
|
||||
.. __: http://en.wikipedia.org/wiki/Prototype_pattern
|
||||
|
27
Creational/Prototype/Tests/PrototypeTest.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\Pool\Tests;
|
||||
|
||||
use DesignPatterns\Creational\Prototype\BarBookPrototype;
|
||||
use DesignPatterns\Creational\Prototype\FooBookPrototype;
|
||||
|
||||
class PrototypeTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testCanGetFooBook()
|
||||
{
|
||||
$fooPrototype = new FooBookPrototype();
|
||||
$barPrototype = new BarBookPrototype();
|
||||
|
||||
for ($i = 0; $i < 10; $i++) {
|
||||
$book = clone $fooPrototype;
|
||||
$book->setTitle('Foo Book No ' . $i);
|
||||
$this->assertInstanceOf('DesignPatterns\Creational\Prototype\FooBookPrototype', $book);
|
||||
}
|
||||
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$book = clone $barPrototype;
|
||||
$book->setTitle('Bar Book No ' . $i);
|
||||
$this->assertInstanceOf('DesignPatterns\Creational\Prototype\BarBookPrototype', $book);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\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);
|
||||
}
|
||||
|
||||
for ($i = 0; $i < 5000; $i++) {
|
||||
$book = clone $barPrototype;
|
||||
$book->setTitle('Bar Book No '.$i);
|
||||
}
|
@@ -2,17 +2,9 @@
|
||||
|
||||
namespace DesignPatterns\Creational\SimpleFactory;
|
||||
|
||||
/**
|
||||
* Bicycle is a bicycle.
|
||||
*/
|
||||
class Bicycle implements VehicleInterface
|
||||
class Bicycle
|
||||
{
|
||||
/**
|
||||
* @param mixed $destination
|
||||
*
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function driveTo($destination)
|
||||
public function driveTo(string $destination)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@@ -6,11 +6,9 @@ Purpose
|
||||
|
||||
SimpleFactory is a simple factory pattern.
|
||||
|
||||
It differs from the static factory because it is NOT static and as you
|
||||
know: static => global => evil!
|
||||
|
||||
Therefore, you can have multiple factories, differently parametrized,
|
||||
you can subclass it and you can mock-up it.
|
||||
It differs from the static factory because it is not static.
|
||||
Therefore, you can have multiple factories, differently parametrized, you can subclass it and you can mock it.
|
||||
It always should be preferred over a static factory!
|
||||
|
||||
UML Diagram
|
||||
-----------
|
||||
@@ -42,12 +40,6 @@ Bicycle.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
Scooter.php
|
||||
|
||||
.. literalinclude:: Scooter.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
|
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\SimpleFactory;
|
||||
|
||||
/**
|
||||
* Scooter is a Scooter.
|
||||
*/
|
||||
class Scooter implements VehicleInterface
|
||||
{
|
||||
/**
|
||||
* @param mixed $destination
|
||||
*/
|
||||
public function driveTo($destination)
|
||||
{
|
||||
}
|
||||
}
|
@@ -2,44 +2,10 @@
|
||||
|
||||
namespace DesignPatterns\Creational\SimpleFactory;
|
||||
|
||||
/**
|
||||
* class SimpleFactory.
|
||||
*/
|
||||
class SimpleFactory
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $typeList;
|
||||
|
||||
/**
|
||||
* You can imagine to inject your own type list or merge with
|
||||
* the default ones...
|
||||
*/
|
||||
public function __construct()
|
||||
public function createBicycle(): Bicycle
|
||||
{
|
||||
$this->typeList = array(
|
||||
'bicycle' => __NAMESPACE__.'\Bicycle',
|
||||
'other' => __NAMESPACE__.'\Scooter',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a vehicle.
|
||||
*
|
||||
* @param string $type a known type key
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return VehicleInterface a new instance of VehicleInterface
|
||||
*/
|
||||
public function createVehicle($type)
|
||||
{
|
||||
if (!array_key_exists($type, $this->typeList)) {
|
||||
throw new \InvalidArgumentException("$type is not valid vehicle");
|
||||
}
|
||||
$className = $this->typeList[$type];
|
||||
|
||||
return new $className();
|
||||
return new Bicycle();
|
||||
}
|
||||
}
|
||||
|
@@ -4,40 +4,11 @@ namespace DesignPatterns\Creational\SimpleFactory\Tests;
|
||||
|
||||
use DesignPatterns\Creational\SimpleFactory\SimpleFactory;
|
||||
|
||||
/**
|
||||
* SimpleFactoryTest tests the Simple Factory pattern.
|
||||
*/
|
||||
class SimpleFactoryTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $factory;
|
||||
|
||||
protected function setUp()
|
||||
public function testCanCreateBicycle()
|
||||
{
|
||||
$this->factory = new SimpleFactory();
|
||||
}
|
||||
|
||||
public function getType()
|
||||
{
|
||||
return array(
|
||||
array('bicycle'),
|
||||
array('other'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getType
|
||||
*/
|
||||
public function testCreation($type)
|
||||
{
|
||||
$obj = $this->factory->createVehicle($type);
|
||||
$this->assertInstanceOf('DesignPatterns\Creational\SimpleFactory\VehicleInterface', $obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testBadType()
|
||||
{
|
||||
$this->factory->createVehicle('car');
|
||||
$bicycle = (new SimpleFactory())->createBicycle();
|
||||
$this->assertInstanceOf('DesignPatterns\Creational\SimpleFactory\Bicycle', $bicycle);
|
||||
}
|
||||
}
|
||||
|
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\SimpleFactory;
|
||||
|
||||
/**
|
||||
* VehicleInterface is a contract for a vehicle.
|
||||
*/
|
||||
interface VehicleInterface
|
||||
{
|
||||
/**
|
||||
* @param mixed $destination
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function driveTo($destination);
|
||||
}
|
@@ -1,36 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Diagram>
|
||||
<ID>PHP</ID>
|
||||
<OriginalElement>\DesignPatterns\Creational\SimpleFactory\SimpleFactory</OriginalElement>
|
||||
<nodes>
|
||||
<node x="173.0" y="97.0">\DesignPatterns\Creational\SimpleFactory\Scooter</node>
|
||||
<node x="0.0" y="189.0">\DesignPatterns\Creational\SimpleFactory\SimpleFactory</node>
|
||||
<node x="86.5" y="0.0">\DesignPatterns\Creational\SimpleFactory\VehicleInterface</node>
|
||||
<node x="0.0" y="97.0">\DesignPatterns\Creational\SimpleFactory\Bicycle</node>
|
||||
</nodes>
|
||||
<notes />
|
||||
<edges>
|
||||
<edge source="\DesignPatterns\Creational\SimpleFactory\Bicycle" target="\DesignPatterns\Creational\SimpleFactory\VehicleInterface">
|
||||
<point x="0.0" y="-23.5" />
|
||||
<point x="76.5" y="72.0" />
|
||||
<point x="124.75" y="72.0" />
|
||||
<point x="-38.25" y="23.5" />
|
||||
</edge>
|
||||
<edge source="\DesignPatterns\Creational\SimpleFactory\Scooter" target="\DesignPatterns\Creational\SimpleFactory\VehicleInterface">
|
||||
<point x="0.0" y="-23.5" />
|
||||
<point x="249.5" y="72.0" />
|
||||
<point x="201.25" y="72.0" />
|
||||
<point x="38.25" y="23.5" />
|
||||
</edge>
|
||||
</edges>
|
||||
<settings layout="Hierarchic Group" zoom="1.0" x="163.0" y="139.0" />
|
||||
<SelectedNodes />
|
||||
<Categories>
|
||||
<Category>Fields</Category>
|
||||
<Category>Constants</Category>
|
||||
<Category>Constructors</Category>
|
||||
<Category>Methods</Category>
|
||||
</Categories>
|
||||
<VISIBILITY>private</VISIBILITY>
|
||||
</Diagram>
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Diagram>
|
||||
<ID>PHP</ID>
|
||||
<OriginalElement>\DesignPatterns\Creational\SimpleFactory\Bicycle</OriginalElement>
|
||||
<nodes>
|
||||
<node x="0.0" y="0.0">\DesignPatterns\Creational\SimpleFactory\Bicycle</node>
|
||||
<node x="0.0" y="96.0">\DesignPatterns\Creational\SimpleFactory\SimpleFactory</node>
|
||||
</nodes>
|
||||
<notes />
|
||||
<edges />
|
||||
<settings layout="Hierarchic Group" zoom="1.0" x="60.0" y="51.5" />
|
||||
<SelectedNodes />
|
||||
<Categories>
|
||||
<Category>Methods</Category>
|
||||
<Category>Constants</Category>
|
||||
<Category>Fields</Category>
|
||||
</Categories>
|
||||
<VISIBILITY>private</VISIBILITY>
|
||||
</Diagram>
|
||||
|
||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 39 KiB |
@@ -2,22 +2,17 @@
|
||||
|
||||
namespace DesignPatterns\Creational\Singleton;
|
||||
|
||||
/**
|
||||
* class Singleton.
|
||||
*/
|
||||
class Singleton
|
||||
final class Singleton
|
||||
{
|
||||
/**
|
||||
* @var Singleton reference to singleton instance
|
||||
* @var Singleton
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
/**
|
||||
* gets the instance via lazy initialization (created on first usage).
|
||||
*
|
||||
* @return self
|
||||
* gets the instance via lazy initialization (created on first usage)
|
||||
*/
|
||||
public static function getInstance()
|
||||
public static function getInstance(): Singleton
|
||||
{
|
||||
if (null === static::$instance) {
|
||||
static::$instance = new static();
|
||||
@@ -27,33 +22,24 @@ class Singleton
|
||||
}
|
||||
|
||||
/**
|
||||
* is not allowed to call from outside: private!
|
||||
* is not allowed to call from outside to prevent from creating multiple instances,
|
||||
* to use the singleton, you have to obtain the instance from Singleton::getInstance() instead
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* prevent the instance from being cloned.
|
||||
*
|
||||
* @throws SingletonPatternViolationException
|
||||
*
|
||||
* @return void
|
||||
* prevent the instance from being cloned (which would create a second instance of it)
|
||||
*/
|
||||
final public function __clone()
|
||||
private function __clone()
|
||||
{
|
||||
throw new SingletonPatternViolationException('This is a Singleton. Clone is forbidden');
|
||||
}
|
||||
|
||||
/**
|
||||
* prevent from being unserialized.
|
||||
*
|
||||
* @throws SingletonPatternViolationException
|
||||
*
|
||||
* @return void
|
||||
* prevent from being unserialized (which would create a second instance of it)
|
||||
*/
|
||||
final public function __wakeup()
|
||||
private function __wakeup()
|
||||
{
|
||||
throw new SingletonPatternViolationException('This is a Singleton. __wakeup usage is forbidden');
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Creational\Singleton;
|
||||
|
||||
class SingletonPatternViolationException extends \Exception
|
||||
{
|
||||
}
|
@@ -4,48 +4,14 @@ namespace DesignPatterns\Creational\Singleton\Tests;
|
||||
|
||||
use DesignPatterns\Creational\Singleton\Singleton;
|
||||
|
||||
/**
|
||||
* SingletonTest tests the singleton pattern.
|
||||
*/
|
||||
class SingletonTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testUniqueness()
|
||||
{
|
||||
$firstCall = Singleton::getInstance();
|
||||
$this->assertInstanceOf('DesignPatterns\Creational\Singleton\Singleton', $firstCall);
|
||||
$secondCall = Singleton::getInstance();
|
||||
|
||||
$this->assertInstanceOf('DesignPatterns\Creational\Singleton\Singleton', $firstCall);
|
||||
$this->assertSame($firstCall, $secondCall);
|
||||
}
|
||||
|
||||
public function testNoConstructor()
|
||||
{
|
||||
$obj = Singleton::getInstance();
|
||||
|
||||
$refl = new \ReflectionObject($obj);
|
||||
$meth = $refl->getMethod('__construct');
|
||||
$this->assertTrue($meth->isPrivate());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \DesignPatterns\Creational\Singleton\SingletonPatternViolationException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testNoCloneAllowed()
|
||||
{
|
||||
$obj1 = Singleton::getInstance();
|
||||
$obj2 = clone $obj1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \DesignPatterns\Creational\Singleton\SingletonPatternViolationException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testNoSerializationAllowed()
|
||||
{
|
||||
$obj1 = Singleton::getInstance();
|
||||
$serialized = serialize($obj1);
|
||||
$obj2 = unserialize($serialized);
|
||||
}
|
||||
}
|
||||
|
@@ -2,9 +2,6 @@
|
||||
|
||||
namespace DesignPatterns\Creational\StaticFactory;
|
||||
|
||||
/**
|
||||
* Class FormatNumber.
|
||||
*/
|
||||
class FormatNumber implements FormatterInterface
|
||||
{
|
||||
}
|
||||
|
@@ -2,9 +2,6 @@
|
||||
|
||||
namespace DesignPatterns\Creational\StaticFactory;
|
||||
|
||||
/**
|
||||
* Class FormatString.
|
||||
*/
|
||||
class FormatString implements FormatterInterface
|
||||
{
|
||||
}
|
||||
|
@@ -2,9 +2,6 @@
|
||||
|
||||
namespace DesignPatterns\Creational\StaticFactory;
|
||||
|
||||
/**
|
||||
* Class FormatterInterface.
|
||||
*/
|
||||
interface FormatterInterface
|
||||
{
|
||||
}
|
||||
|
@@ -3,30 +3,26 @@
|
||||
namespace DesignPatterns\Creational\StaticFactory;
|
||||
|
||||
/**
|
||||
* Note1: Remember, static => global => evil
|
||||
* Note1: Remember, static means global state which is evil because it can't be mocked for tests
|
||||
* Note2: Cannot be subclassed or mock-upped or have multiple different instances.
|
||||
*/
|
||||
class StaticFactory
|
||||
final class StaticFactory
|
||||
{
|
||||
/**
|
||||
* the parametrized function to get create an instance.
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return FormatterInterface
|
||||
*/
|
||||
public static function factory($type)
|
||||
public static function factory(string $type): FormatterInterface
|
||||
{
|
||||
$className = __NAMESPACE__.'\Format'.ucfirst($type);
|
||||
|
||||
if (!class_exists($className)) {
|
||||
throw new \InvalidArgumentException('Missing format class.');
|
||||
if ($type == 'number') {
|
||||
return new FormatNumber();
|
||||
}
|
||||
|
||||
return new $className();
|
||||
if ($type == 'string') {
|
||||
return new FormatString();
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException('Unknown format given');
|
||||
}
|
||||
}
|
||||
|
@@ -4,33 +4,29 @@ namespace DesignPatterns\Creational\StaticFactory\Tests;
|
||||
|
||||
use DesignPatterns\Creational\StaticFactory\StaticFactory;
|
||||
|
||||
/**
|
||||
* Tests for Static Factory pattern.
|
||||
*/
|
||||
class StaticFactoryTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function getTypeList()
|
||||
public function testCanCreateNumberFormatter()
|
||||
{
|
||||
return array(
|
||||
array('string'),
|
||||
array('number'),
|
||||
$this->assertInstanceOf(
|
||||
'DesignPatterns\Creational\StaticFactory\FormatNumber',
|
||||
StaticFactory::factory('number')
|
||||
);
|
||||
}
|
||||
|
||||
public function testCanCreateStringFormatter()
|
||||
{
|
||||
$this->assertInstanceOf(
|
||||
'DesignPatterns\Creational\StaticFactory\FormatString',
|
||||
StaticFactory::factory('string')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getTypeList
|
||||
*/
|
||||
public function testCreation($type)
|
||||
{
|
||||
$obj = StaticFactory::factory($type);
|
||||
$this->assertInstanceOf('DesignPatterns\Creational\StaticFactory\FormatterInterface', $obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testException()
|
||||
{
|
||||
StaticFactory::factory('');
|
||||
StaticFactory::factory('object');
|
||||
}
|
||||
}
|
||||
|