Merged branch master into translate-template

This commit is contained in:
Axel Pardemann
2016-09-23 11:44:18 -05:00
288 changed files with 9359 additions and 9024 deletions

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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>';
}
}

View File

@@ -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);
}
}

View File

@@ -0,0 +1,8 @@
<?php
namespace DesignPatterns\Creational\AbstractFactory;
class HtmlText extends Text
{
// do something here
}

View File

@@ -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));
}
}

View File

@@ -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));
}
}

View File

@@ -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);
}
}

View File

@@ -0,0 +1,8 @@
<?php
namespace DesignPatterns\Creational\AbstractFactory;
class JsonText extends Text
{
// do something here
}

View File

@@ -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();
}

View File

@@ -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;
}
}

View File

@@ -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:

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 33 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 90 KiB

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -2,9 +2,6 @@
namespace DesignPatterns\Creational\Builder\Parts;
/**
* Car is a car.
*/
class Car extends Vehicle
{
}

View File

@@ -2,9 +2,6 @@
namespace DesignPatterns\Creational\Builder\Parts;
/**
* Class Door.
*/
class Door
{
}

View File

@@ -2,9 +2,6 @@
namespace DesignPatterns\Creational\Builder\Parts;
/**
* Class Engine.
*/
class Engine
{
}

View File

@@ -2,9 +2,6 @@
namespace DesignPatterns\Creational\Builder\Parts;
/**
* Bike is a bike.
*/
class Bike extends Vehicle
class Truck extends Vehicle
{
}

View File

@@ -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)
{

View File

@@ -2,9 +2,6 @@
namespace DesignPatterns\Creational\Builder\Parts;
/**
* Class Wheel.
*/
class Wheel
{
}

View File

@@ -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:

View File

@@ -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);
}
}

View 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;
}
}

View File

@@ -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;
}

View 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;
}
}

View 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
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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");
}

View File

@@ -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");
}

View File

@@ -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()
{
}
}

View File

@@ -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
----

View File

@@ -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');
}
}

View File

@@ -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);
}

View File

@@ -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()
{

View 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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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

View 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);
}
}

View File

@@ -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);
}
}

View File

@@ -1,8 +0,0 @@
<?php
namespace DesignPatterns\Creational\Pool\Tests;
class TestWorker
{
public $id = 1;
}

View File

@@ -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);
}
}

View 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);
}
}

View File

@@ -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()
{
}

View File

@@ -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;

View File

@@ -2,16 +2,13 @@
namespace DesignPatterns\Creational\Prototype;
/**
* Class FooBookPrototype.
*/
class FooBookPrototype extends BookPrototype
{
/**
* @var string
*/
protected $category = 'Foo';
/**
* empty clone.
*/
public function __clone()
{
}

View File

@@ -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

View 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);
}
}
}

View File

@@ -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);
}

View File

@@ -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)
{
}
}

View File

@@ -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
-----

View File

@@ -1,16 +0,0 @@
<?php
namespace DesignPatterns\Creational\SimpleFactory;
/**
* Scooter is a Scooter.
*/
class Scooter implements VehicleInterface
{
/**
* @param mixed $destination
*/
public function driveTo($destination)
{
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 17 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

@@ -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');
}
}

View File

@@ -1,7 +0,0 @@
<?php
namespace DesignPatterns\Creational\Singleton;
class SingletonPatternViolationException extends \Exception
{
}

View File

@@ -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);
}
}

View File

@@ -2,9 +2,6 @@
namespace DesignPatterns\Creational\StaticFactory;
/**
* Class FormatNumber.
*/
class FormatNumber implements FormatterInterface
{
}

View File

@@ -2,9 +2,6 @@
namespace DesignPatterns\Creational\StaticFactory;
/**
* Class FormatString.
*/
class FormatString implements FormatterInterface
{
}

View File

@@ -2,9 +2,6 @@
namespace DesignPatterns\Creational\StaticFactory;
/**
* Class FormatterInterface.
*/
interface FormatterInterface
{
}

View File

@@ -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');
}
}

View File

@@ -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');
}
}