mirror of
https://github.com/DesignPatternsPHP/DesignPatternsPHP.git
synced 2025-07-31 12:10:10 +02:00
start a restructure
This commit is contained in:
40
Creational/AbstractFactory/AbstractFactory.php
Normal file
40
Creational/AbstractFactory/AbstractFactory.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\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 is two ways
|
||||
* of rendering : HTML or JSON.
|
||||
*
|
||||
* Therefore 4 concretes classes, but the client just need to know this contract
|
||||
* to build a correct http response (for a html page or for an ajax request)
|
||||
*/
|
||||
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 = '');
|
||||
}
|
23
Creational/AbstractFactory/Html/Picture.php
Normal file
23
Creational/AbstractFactory/Html/Picture.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\AbstractFactory\Html;
|
||||
|
||||
use DesignPatterns\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);
|
||||
}
|
||||
}
|
23
Creational/AbstractFactory/Html/Text.php
Normal file
23
Creational/AbstractFactory/Html/Text.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\AbstractFactory\Html;
|
||||
|
||||
use DesignPatterns\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>';
|
||||
}
|
||||
}
|
36
Creational/AbstractFactory/HtmlFactory.php
Normal file
36
Creational/AbstractFactory/HtmlFactory.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\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 = '')
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
23
Creational/AbstractFactory/Json/Picture.php
Normal file
23
Creational/AbstractFactory/Json/Picture.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\AbstractFactory\Json;
|
||||
|
||||
use DesignPatterns\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));
|
||||
}
|
||||
}
|
23
Creational/AbstractFactory/Json/Text.php
Normal file
23
Creational/AbstractFactory/Json/Text.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\AbstractFactory\Json;
|
||||
|
||||
use DesignPatterns\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));
|
||||
}
|
||||
}
|
38
Creational/AbstractFactory/JsonFactory.php
Normal file
38
Creational/AbstractFactory/JsonFactory.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\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 = '')
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
20
Creational/AbstractFactory/MediaInterface.php
Normal file
20
Creational/AbstractFactory/MediaInterface.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\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();
|
||||
}
|
30
Creational/AbstractFactory/Picture.php
Normal file
30
Creational/AbstractFactory/Picture.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\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;
|
||||
}
|
||||
}
|
6
Creational/AbstractFactory/README.md
Normal file
6
Creational/AbstractFactory/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Abstract Factory
|
||||
|
||||
## Purpose
|
||||
|
||||
To create series of related or dependent objects without specifying their concrete classes.
|
||||
Usually the created classes all implement the same interface. The client of the abstract factory does not care about how these objects are created, he just knows how they go together.
|
44
Creational/AbstractFactory/Test/AbstractFactoryTest.php
Normal file
44
Creational/AbstractFactory/Test/AbstractFactoryTest.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Tests\AbstractFactory;
|
||||
|
||||
use DesignPatterns\AbstractFactory\AbstractFactory;
|
||||
use DesignPatterns\AbstractFactory\HtmlFactory;
|
||||
use DesignPatterns\AbstractFactory\JsonFactory;
|
||||
|
||||
/**
|
||||
* AbstractFactoryTest tests concrete factories
|
||||
*/
|
||||
class AbstractFactoryTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function getFactories()
|
||||
{
|
||||
return array(
|
||||
array(new JsonFactory()),
|
||||
array(new HtmlFactory())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
$article = array(
|
||||
$factory->createText('Lorem Ipsum'),
|
||||
$factory->createPicture('/image.jpg', 'caption'),
|
||||
$factory->createText('footnotes')
|
||||
);
|
||||
|
||||
$this->assertContainsOnly('DesignPatterns\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
|
||||
*/
|
||||
}
|
||||
}
|
22
Creational/AbstractFactory/Text.php
Normal file
22
Creational/AbstractFactory/Text.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\AbstractFactory;
|
||||
|
||||
/**
|
||||
* Class Text
|
||||
*/
|
||||
abstract class Text implements MediaInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $text;
|
||||
|
||||
/**
|
||||
* @param string $text
|
||||
*/
|
||||
public function __construct($text)
|
||||
{
|
||||
$this->text = (string) $text;
|
||||
}
|
||||
}
|
55
Creational/Builder/BikeBuilder.php
Normal file
55
Creational/Builder/BikeBuilder.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\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;
|
||||
}
|
||||
}
|
34
Creational/Builder/BuilderInterface.php
Normal file
34
Creational/Builder/BuilderInterface.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Builder;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
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();
|
||||
}
|
58
Creational/Builder/CarBuilder.php
Normal file
58
Creational/Builder/CarBuilder.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Builder;
|
||||
|
||||
/**
|
||||
* CarBuilder builds car
|
||||
*/
|
||||
class CarBuilder implements BuilderInterface
|
||||
{
|
||||
/**
|
||||
* @var Parts\Car
|
||||
*/
|
||||
protected $car;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function addDoors()
|
||||
{
|
||||
$this->car->setPart('rightdoor', new Parts\Door());
|
||||
$this->car->setPart('leftDoor', 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());
|
||||
$this->car->setPart('wheelRF', new Parts\Wheel());
|
||||
$this->car->setPart('wheelLR', new Parts\Wheel());
|
||||
$this->car->setPart('wheelRR', new Parts\Wheel());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function createVehicle()
|
||||
{
|
||||
$this->car = new Parts\Car();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Parts\Car
|
||||
*/
|
||||
public function getVehicle()
|
||||
{
|
||||
return $this->car;
|
||||
}
|
||||
}
|
30
Creational/Builder/Director.php
Normal file
30
Creational/Builder/Director.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Builder;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* You can also inject many builders instead of one to build more complex objects
|
||||
*/
|
||||
class Director
|
||||
{
|
||||
|
||||
/**
|
||||
* The director don't know 'bout concrete part
|
||||
*
|
||||
* @param BuilderInterface $builder
|
||||
*
|
||||
* @return Parts\Vehicle
|
||||
*/
|
||||
public function build(BuilderInterface $builder)
|
||||
{
|
||||
$builder->createVehicle();
|
||||
$builder->addDoors();
|
||||
$builder->addEngine();
|
||||
$builder->addWheel();
|
||||
|
||||
return $builder->getVehicle();
|
||||
}
|
||||
}
|
11
Creational/Builder/Parts/Bike.php
Normal file
11
Creational/Builder/Parts/Bike.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Builder\Parts;
|
||||
|
||||
/**
|
||||
* Bike is a bike
|
||||
*/
|
||||
class Bike extends Vehicle
|
||||
{
|
||||
|
||||
}
|
11
Creational/Builder/Parts/Car.php
Normal file
11
Creational/Builder/Parts/Car.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Builder\Parts;
|
||||
|
||||
/**
|
||||
* Car is a car
|
||||
*/
|
||||
class Car extends Vehicle
|
||||
{
|
||||
|
||||
}
|
11
Creational/Builder/Parts/Door.php
Normal file
11
Creational/Builder/Parts/Door.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Builder\Parts;
|
||||
|
||||
/**
|
||||
* Class Door
|
||||
*/
|
||||
class Door
|
||||
{
|
||||
|
||||
}
|
11
Creational/Builder/Parts/Engine.php
Normal file
11
Creational/Builder/Parts/Engine.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Builder\Parts;
|
||||
|
||||
/**
|
||||
* Class Engine
|
||||
*/
|
||||
class Engine
|
||||
{
|
||||
|
||||
}
|
10
Creational/Builder/Parts/README.md
Normal file
10
Creational/Builder/Parts/README.md
Normal file
@@ -0,0 +1,10 @@
|
||||
#
|
||||
|
||||
# Purpose
|
||||
|
||||
|
||||
|
||||
# Examples
|
||||
|
||||
*
|
||||
|
23
Creational/Builder/Parts/Vehicle.php
Normal file
23
Creational/Builder/Parts/Vehicle.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Builder\Parts;
|
||||
|
||||
/**
|
||||
* VehicleInterface is a contract for a vehicle
|
||||
*/
|
||||
abstract class Vehicle
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function setPart($key, $value)
|
||||
{
|
||||
$this->data[$key] = $value;
|
||||
}
|
||||
}
|
11
Creational/Builder/Parts/Wheel.php
Normal file
11
Creational/Builder/Parts/Wheel.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Builder\Parts;
|
||||
|
||||
/**
|
||||
* Class Wheel
|
||||
*/
|
||||
class Wheel
|
||||
{
|
||||
|
||||
}
|
15
Creational/Builder/README.md
Normal file
15
Creational/Builder/README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Builder
|
||||
|
||||
## Purpose
|
||||
|
||||
Builder is an interface that build parts of a complex object.
|
||||
|
||||
Sometimes, if the builder has a better knowledge of what it builds, this interface could be an abstract class with default methods (aka adapter).
|
||||
|
||||
If you have a complex inheritance tree for objects, it is logical to have a complex inheritance tree for builders too.
|
||||
|
||||
Note: Builders have often a fluent interface, see the mock builder of PHPUnit for example.
|
||||
|
||||
## Examples
|
||||
|
||||
* PHPUnit: Mock Builder
|
42
Creational/Builder/Test/DirectorTest.php
Normal file
42
Creational/Builder/Test/DirectorTest.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Tests\Builder;
|
||||
|
||||
use DesignPatterns\Builder\Director;
|
||||
use DesignPatterns\Builder\CarBuilder;
|
||||
use DesignPatterns\Builder\BikeBuilder;
|
||||
use DesignPatterns\Builder\BuilderInterface;
|
||||
|
||||
/**
|
||||
* DirectorTest tests the builder pattern
|
||||
*/
|
||||
class DirectorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
protected $director;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->director = new Director();
|
||||
}
|
||||
|
||||
public function getBuilder()
|
||||
{
|
||||
return array(
|
||||
array(new CarBuilder()),
|
||||
array(new BikeBuilder())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Here we test the build process. Notice that the client don't know
|
||||
* anything about the contrete builder.
|
||||
*
|
||||
* @dataProvider getBuilder
|
||||
*/
|
||||
public function testBuild(BuilderInterface $builder)
|
||||
{
|
||||
$newVehicle = $this->director->build($builder);
|
||||
$this->assertInstanceOf('DesignPatterns\Builder\Parts\Vehicle', $newVehicle);
|
||||
}
|
||||
}
|
24
Creational/FactoryMethod/Bicycle.php
Normal file
24
Creational/FactoryMethod/Bicycle.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\FactoryMethod;
|
||||
|
||||
/**
|
||||
* Bicycle is a bicycle
|
||||
*/
|
||||
class Bicycle implements VehicleInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $color;
|
||||
|
||||
/**
|
||||
* sets the color of the bicycle
|
||||
*
|
||||
* @param string $rgb
|
||||
*/
|
||||
public function setColor($rgb)
|
||||
{
|
||||
$this->color = $rgb;
|
||||
}
|
||||
}
|
39
Creational/FactoryMethod/FactoryMethod.php
Normal file
39
Creational/FactoryMethod/FactoryMethod.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\FactoryMethod;
|
||||
|
||||
/**
|
||||
* class FactoryMethod
|
||||
*/
|
||||
abstract class FactoryMethod
|
||||
{
|
||||
|
||||
const CHEAP = 1;
|
||||
const FAST = 2;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Creates a new vehicle
|
||||
*
|
||||
* @param int $type
|
||||
*
|
||||
* @return VehicleInterface a new vehicle
|
||||
*/
|
||||
public function create($type)
|
||||
{
|
||||
$obj = $this->createVehicle($type);
|
||||
$obj->setColor("#f00");
|
||||
|
||||
return $obj;
|
||||
}
|
||||
}
|
22
Creational/FactoryMethod/Ferrari.php
Normal file
22
Creational/FactoryMethod/Ferrari.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\FactoryMethod;
|
||||
|
||||
/**
|
||||
* Ferrari is a italian car
|
||||
*/
|
||||
class Ferrari implements VehicleInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $color;
|
||||
|
||||
/**
|
||||
* @param string $rgb
|
||||
*/
|
||||
public function setColor($rgb)
|
||||
{
|
||||
$this->color = $rgb;
|
||||
}
|
||||
}
|
31
Creational/FactoryMethod/GermanFactory.php
Normal file
31
Creational/FactoryMethod/GermanFactory.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\FactoryMethod;
|
||||
|
||||
/**
|
||||
* GermanFactory is a vehicle factory in Germany
|
||||
*/
|
||||
class GermanFactory extends FactoryMethod
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createVehicle($type)
|
||||
{
|
||||
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();
|
||||
|
||||
return $obj;
|
||||
break;
|
||||
default:
|
||||
throw new \InvalidArgumentException("$type is not a valid vehicle");
|
||||
}
|
||||
}
|
||||
}
|
26
Creational/FactoryMethod/ItalianFactory.php
Normal file
26
Creational/FactoryMethod/ItalianFactory.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\FactoryMethod;
|
||||
|
||||
/**
|
||||
* ItalianFactory is vehicle factory in Italy
|
||||
*/
|
||||
class ItalianFactory extends FactoryMethod
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createVehicle($type)
|
||||
{
|
||||
switch ($type) {
|
||||
case parent::CHEAP:
|
||||
return new Bicycle();
|
||||
break;
|
||||
case parent::FAST:
|
||||
return new Ferrari();
|
||||
break;
|
||||
default:
|
||||
throw new \InvalidArgumentException("$type is not a valid vehicle");
|
||||
}
|
||||
}
|
||||
}
|
31
Creational/FactoryMethod/Porsche.php
Normal file
31
Creational/FactoryMethod/Porsche.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\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()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
11
Creational/FactoryMethod/README.md
Normal file
11
Creational/FactoryMethod/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Factory Method
|
||||
|
||||
## Purpose
|
||||
|
||||
The good point over the SimpleFactory is you can subclass it to implement different ways to create objects
|
||||
|
||||
For simple case, this abstract class could be just an interface
|
||||
|
||||
This pattern is a "real" Design Pattern because it achieves the "Dependency Inversion Principle" a.k.a the "D" in S.O.L.I.D principles.
|
||||
|
||||
It means the FactoryMethod class depends on abstractions, not concrete classes. This is the real trick compared to SimpleFactory or StaticFactory.
|
50
Creational/FactoryMethod/Test/FactoryMethodTest.php
Normal file
50
Creational/FactoryMethod/Test/FactoryMethodTest.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Tests\FactoryMethod;
|
||||
|
||||
use DesignPatterns\FactoryMethod\FactoryMethod;
|
||||
use DesignPatterns\FactoryMethod\GermanFactory;
|
||||
use DesignPatterns\FactoryMethod\ItalianFactory;
|
||||
|
||||
/**
|
||||
* FactoryMethodTest tests the factory method pattern
|
||||
*/
|
||||
class FactoryMethodTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
protected $type = array(
|
||||
FactoryMethod::CHEAP,
|
||||
FactoryMethod::FAST
|
||||
);
|
||||
|
||||
public function getShop()
|
||||
{
|
||||
return array(
|
||||
array(new GermanFactory()),
|
||||
array(new ItalianFactory())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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\FactoryMethod\VehicleInterface', $vehicle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getShop
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessage spaceship is not a valid vehicle
|
||||
*/
|
||||
public function testUnknownType(FactoryMethod $shop)
|
||||
{
|
||||
$shop->create('spaceship');
|
||||
}
|
||||
}
|
16
Creational/FactoryMethod/VehicleInterface.php
Normal file
16
Creational/FactoryMethod/VehicleInterface.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\FactoryMethod;
|
||||
|
||||
/**
|
||||
* VehicleInterface is a contract for a vehicle
|
||||
*/
|
||||
interface VehicleInterface
|
||||
{
|
||||
/**
|
||||
* sets the color of the vehicle
|
||||
*
|
||||
* @param string $rgb
|
||||
*/
|
||||
public function setColor($rgb);
|
||||
}
|
74
Creational/Multiton/Multiton.php
Normal file
74
Creational/Multiton/Multiton.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns;
|
||||
|
||||
/**
|
||||
* class Multiton
|
||||
*/
|
||||
class Multiton
|
||||
{
|
||||
/**
|
||||
*
|
||||
* the first instance
|
||||
*/
|
||||
const INSTANCE_1 = '1';
|
||||
|
||||
/**
|
||||
*
|
||||
* the second instance
|
||||
*/
|
||||
const INSTANCE_2 = '2';
|
||||
|
||||
/**
|
||||
* holds the named instances
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $instances = array();
|
||||
|
||||
/**
|
||||
* should not be called from outside: private!
|
||||
*
|
||||
*/
|
||||
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)
|
||||
{
|
||||
if (!array_key_exists($instanceName, self::$instances)) {
|
||||
self::$instances[$instanceName] = new self();
|
||||
}
|
||||
|
||||
return self::$instances[$instanceName];
|
||||
}
|
||||
|
||||
/**
|
||||
* prevent instance from being cloned
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function __clone()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* prevent instance from being unserialized
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function __wakeup()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
12
Creational/Multiton/README.md
Normal file
12
Creational/Multiton/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Multiton
|
||||
|
||||
**THIS IS CONSIDERED TO BE AN ANTI-PATTERN! FOR BETTER TESTABILITY AND MAINTAINABILITY USE DEPENDENCY INJECTION!**
|
||||
|
||||
# Purpose
|
||||
|
||||
To have only a list of named instances that are used, like a singleton but with n instances.
|
||||
|
||||
# Examples
|
||||
|
||||
* 2 DB Connectors, e.g. one for MySQL, the other for SQLite
|
||||
* multiple Loggers (one for debug messages, one for errors)
|
22
Creational/Prototype/BarBookPrototype.php
Normal file
22
Creational/Prototype/BarBookPrototype.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Prototype;
|
||||
|
||||
/**
|
||||
* Class BarBookPrototype
|
||||
*/
|
||||
class BarBookPrototype extends BookPrototype
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $category = 'Bar';
|
||||
|
||||
/**
|
||||
* empty clone
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
41
Creational/Prototype/BookPrototype.php
Normal file
41
Creational/Prototype/BookPrototype.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Prototype;
|
||||
|
||||
/**
|
||||
* class BookPrototype
|
||||
*/
|
||||
abstract class BookPrototype
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $title;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $category;
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @return void
|
||||
*/
|
||||
abstract public function __clone();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $title
|
||||
*/
|
||||
public function setTitle($title)
|
||||
{
|
||||
$this->title = $title;
|
||||
}
|
||||
}
|
19
Creational/Prototype/FooBookPrototype.php
Normal file
19
Creational/Prototype/FooBookPrototype.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Prototype;
|
||||
|
||||
/**
|
||||
* Class FooBookPrototype
|
||||
*/
|
||||
class FooBookPrototype extends BookPrototype
|
||||
{
|
||||
protected $category = 'Foo';
|
||||
|
||||
/**
|
||||
* empty clone
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
9
Creational/Prototype/README.md
Normal file
9
Creational/Prototype/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Prototype
|
||||
|
||||
## Purpose
|
||||
|
||||
To avoid the cost of creating objects the standard way (new Foo()) and instead create a prototype and clone it
|
||||
|
||||
## Examples
|
||||
|
||||
* Large amounts of data (e.g. create 1,000,000 rows in a database at once via a ORM)
|
17
Creational/Prototype/index.php
Normal file
17
Creational/Prototype/index.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Prototype;
|
||||
|
||||
$fooPrototype = new FooBookPrototype();
|
||||
$barPrototype = new BarBookPrototype();
|
||||
|
||||
// now lets say we need 10,000 books of foo and 5,000 of bar ...
|
||||
for ($i = 0; $i < 10000; $i++) {
|
||||
$book = clone $fooPrototype;
|
||||
$book->setTitle('Foo Book No ' . $i);
|
||||
}
|
||||
|
||||
for ($i = 0; $i < 5000; $i++) {
|
||||
$book = clone $barPrototype;
|
||||
$book->setTitle('Bar Book No ' . $i);
|
||||
}
|
19
Creational/SimpleFactory/Bicycle.php
Normal file
19
Creational/SimpleFactory/Bicycle.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\SimpleFactory;
|
||||
|
||||
/**
|
||||
* Bicycle is a bicycle
|
||||
*/
|
||||
class Bicycle implements VehicleInterface
|
||||
{
|
||||
/**
|
||||
* @param mixed $destination
|
||||
*
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function driveTo($destination)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
44
Creational/SimpleFactory/ConcreteFactory.php
Normal file
44
Creational/SimpleFactory/ConcreteFactory.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\SimpleFactory;
|
||||
|
||||
/**
|
||||
* class ConcreteFactory
|
||||
*/
|
||||
class ConcreteFactory
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $typeList;
|
||||
|
||||
/**
|
||||
* You can imagine to inject your own type list or merge with
|
||||
* the default ones...
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->typeList = array(
|
||||
'bicycle' => __NAMESPACE__ . '\Bicycle',
|
||||
'other' => __NAMESPACE__ . '\Scooter'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a vehicle
|
||||
*
|
||||
* @param string $type a known type key
|
||||
*
|
||||
* @return VehicleInterface a new instance of VehicleInterface
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
9
Creational/SimpleFactory/README.md
Normal file
9
Creational/SimpleFactory/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Simple Factory
|
||||
|
||||
## Purpose
|
||||
|
||||
ConcreteFactory is a simple factory pattern.
|
||||
|
||||
It differs from the static factory because it is NOT static and as you know: static => global => evil!
|
||||
|
||||
Therefore, you can haZ multiple factories, differently parametrized, you can subclass it and you can mock-up it.
|
17
Creational/SimpleFactory/Scooter.php
Normal file
17
Creational/SimpleFactory/Scooter.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\SimpleFactory;
|
||||
|
||||
/**
|
||||
* Scooter is a Scooter
|
||||
*/
|
||||
class Scooter implements VehicleInterface
|
||||
{
|
||||
/**
|
||||
* @param mixed $destination
|
||||
*/
|
||||
public function driveTo($destination)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
45
Creational/SimpleFactory/Test/SimpleFactoryTest.php
Normal file
45
Creational/SimpleFactory/Test/SimpleFactoryTest.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Tests\SimpleFactory;
|
||||
|
||||
use DesignPatterns\SimpleFactory\ConcreteFactory;
|
||||
|
||||
/**
|
||||
* SimpleFactoryTest tests the Simple Factory pattern
|
||||
*/
|
||||
class SimpleFactoryTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
protected $factory;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->factory = new ConcreteFactory();
|
||||
}
|
||||
|
||||
public function getType()
|
||||
{
|
||||
return array(
|
||||
array('bicycle'),
|
||||
array('other')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getType
|
||||
*/
|
||||
public function testCreation($type)
|
||||
{
|
||||
$obj = $this->factory->createVehicle($type);
|
||||
$this->assertInstanceOf('DesignPatterns\SimpleFactory\VehicleInterface', $obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testBadType()
|
||||
{
|
||||
$this->factory->createVehicle('car');
|
||||
}
|
||||
|
||||
}
|
16
Creational/SimpleFactory/VehicleInterface.php
Normal file
16
Creational/SimpleFactory/VehicleInterface.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\SimpleFactory;
|
||||
|
||||
/**
|
||||
* VehicleInterface is a contract for a vehicle
|
||||
*/
|
||||
interface VehicleInterface
|
||||
{
|
||||
/**
|
||||
* @param mixed $destination
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function driveTo($destination);
|
||||
}
|
17
Creational/Singleton/README.md
Normal file
17
Creational/Singleton/README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Singleton
|
||||
|
||||
**THIS IS CONSIDERED TO BE AN ANTI-PATTERN! FOR BETTER TESTABILITY AND MAINTAINABILITY USE DEPENDENCY INJECTION!**
|
||||
|
||||
## Purpose
|
||||
|
||||
To have only one instance of this object in the application that will handle all calls.
|
||||
|
||||
## Examples
|
||||
|
||||
* DB Connector
|
||||
* Logger (may also be a Multiton if there are many log files for several purposes)
|
||||
* Lock file for the application (there is only one in the filesystem ...)
|
||||
|
||||
## Diagram
|
||||
|
||||
<img src="http://yuml.me/diagram/scruffy/class/[Singleton|-instance: Singleton|+getInstance(): Singleton;-__construct(): void;-__clone(): void;-__wakeup(): void]" >
|
58
Creational/Singleton/Singleton.php
Normal file
58
Creational/Singleton/Singleton.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Singleton;
|
||||
|
||||
/**
|
||||
* class Singleton
|
||||
*/
|
||||
class Singleton
|
||||
{
|
||||
/**
|
||||
* @var cached reference to singleton instance
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
/**
|
||||
* gets the instance via lazy initialization (created on first usage)
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
|
||||
if (null === static::$instance) {
|
||||
static::$instance = new static;
|
||||
}
|
||||
|
||||
return static::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* is not allowed to call from outside: private!
|
||||
*
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* prevent the instance from being cloned
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function __clone()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* prevent from being unserialized
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function __wakeup()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
29
Creational/Singleton/Test/SingletonTest.php
Normal file
29
Creational/Singleton/Test/SingletonTest.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Tests\Singleton;
|
||||
|
||||
use DesignPatterns\Singleton\Singleton;
|
||||
|
||||
/**
|
||||
* SingletonTest tests the singleton pattern
|
||||
*/
|
||||
class SingletonTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
public function testUniqueness()
|
||||
{
|
||||
$firstCall = Singleton::getInstance();
|
||||
$this->assertInstanceOf('DesignPatterns\Singleton\Singleton', $firstCall);
|
||||
$secondCall = Singleton::getInstance();
|
||||
$this->assertSame($firstCall, $secondCall);
|
||||
}
|
||||
|
||||
public function testNoConstructor()
|
||||
{
|
||||
$obj = Singleton::getInstance();
|
||||
|
||||
$refl = new \ReflectionObject($obj);
|
||||
$meth = $refl->getMethod('__construct');
|
||||
$this->assertTrue($meth->isPrivate());
|
||||
}
|
||||
}
|
11
Creational/StaticFactory/FormatNumber.php
Normal file
11
Creational/StaticFactory/FormatNumber.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\StaticFactory;
|
||||
|
||||
/**
|
||||
* Class FormatNumber
|
||||
*/
|
||||
class FormatNumber implements FormatterInterface
|
||||
{
|
||||
|
||||
}
|
11
Creational/StaticFactory/FormatString.php
Normal file
11
Creational/StaticFactory/FormatString.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\StaticFactory;
|
||||
|
||||
/**
|
||||
* Class FormatString
|
||||
*/
|
||||
class FormatString implements FormatterInterface
|
||||
{
|
||||
|
||||
}
|
11
Creational/StaticFactory/FormatterInterface.php
Normal file
11
Creational/StaticFactory/FormatterInterface.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\StaticFactory;
|
||||
|
||||
/**
|
||||
* Class FormatterInterface
|
||||
*/
|
||||
interface FormatterInterface
|
||||
{
|
||||
|
||||
}
|
11
Creational/StaticFactory/README.md
Normal file
11
Creational/StaticFactory/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Static Factory
|
||||
|
||||
## Purpose
|
||||
|
||||
Similar to the AbstractFactory, this pattern is used to create series of related or dependent objects.
|
||||
The difference between this and the abstract factory pattern is that the static factory pattern uses just one static
|
||||
method to create all types of objects it can create. It is usually named `factory` or `build`.
|
||||
|
||||
## Examples
|
||||
|
||||
* Zend Framework: `Zend_Cache_Backend` or `_Frontend` use a factory method create cache backends or frontends
|
31
Creational/StaticFactory/StaticFactory.php
Normal file
31
Creational/StaticFactory/StaticFactory.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\StaticFactory;
|
||||
|
||||
/**
|
||||
* Note1: Remember, static => global => evil
|
||||
* Note2: Cannot be subclassed or mock-upped or have multiple different instances
|
||||
*/
|
||||
class StaticFactory
|
||||
{
|
||||
/**
|
||||
* the parametrized function to get create an instance
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
* @return FormatterInterface
|
||||
*/
|
||||
public static function factory($type)
|
||||
{
|
||||
$className = __NAMESPACE__ . '\Format' . ucfirst($type);
|
||||
|
||||
if (!class_exists($className)) {
|
||||
throw new \InvalidArgumentException('Missing format class.');
|
||||
}
|
||||
|
||||
return new $className();
|
||||
}
|
||||
}
|
30
Creational/StaticFactory/Test/StaticFactoryTest.php
Normal file
30
Creational/StaticFactory/Test/StaticFactoryTest.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Tests\StaticFactory;
|
||||
|
||||
use DesignPatterns\StaticFactory\StaticFactory;
|
||||
|
||||
/**
|
||||
* Tests for Static Factory pattern
|
||||
*
|
||||
*/
|
||||
class StaticFactoryTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
public function getTypeList()
|
||||
{
|
||||
return array(
|
||||
array('string'),
|
||||
array('number')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getTypeList
|
||||
*/
|
||||
public function testCreation($type)
|
||||
{
|
||||
$obj = StaticFactory::factory($type);
|
||||
$this->assertInstanceOf('DesignPatterns\StaticFactory\FormatterInterface', $obj);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user