PHP7 FactoryMethod

This commit is contained in:
Dominik Liebler
2016-09-22 13:28:46 +02:00
parent 6a98bcb73b
commit 4760d898a0
11 changed files with 94 additions and 159 deletions

View File

@@ -2,22 +2,14 @@
namespace DesignPatterns\Creational\FactoryMethod; namespace DesignPatterns\Creational\FactoryMethod;
/**
* Bicycle is a bicycle.
*/
class Bicycle implements VehicleInterface class Bicycle implements VehicleInterface
{ {
/** /**
* @var string * @var string
*/ */
protected $color; private $color;
/** public function setColor(string $rgb)
* Sets the color of the bicycle.
*
* @param string $rgb
*/
public function setColor($rgb)
{ {
$this->color = $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; namespace DesignPatterns\Creational\FactoryMethod;
/**
* class FactoryMethod.
*/
abstract class FactoryMethod abstract class FactoryMethod
{ {
const CHEAP = 1; const CHEAP = 'cheap';
const FAST = 2; const FAST = 'fast';
/** abstract protected function createVehicle(string $type): VehicleInterface;
* 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);
/** public function create(string $type): VehicleInterface
* Creates a new vehicle.
*
* @param int $type
*
* @return VehicleInterface a new vehicle
*/
public function create($type)
{ {
$obj = $this->createVehicle($type); $obj = $this->createVehicle($type);
$obj->setColor('#f00'); $obj->setColor('black');
return $obj; 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; namespace DesignPatterns\Creational\FactoryMethod;
/**
* GermanFactory is a vehicle factory in Germany.
*/
class GermanFactory extends FactoryMethod class GermanFactory extends FactoryMethod
{ {
/** protected function createVehicle(string $type): VehicleInterface
* {@inheritdoc}
*/
protected function createVehicle($type)
{ {
switch ($type) { switch ($type) {
case parent::CHEAP: case parent::CHEAP:
return new Bicycle(); return new Bicycle();
break;
case parent::FAST: case parent::FAST:
$obj = new Porsche(); $carMercedes = new CarMercedes();
// we can specialize the way we want some concrete Vehicle since // we can specialize the way we want some concrete Vehicle since we know the class
// we know the class $carMercedes->addAMGTuning();
$obj->addTuningAMG();
return $obj; return $carMercedes;
break;
default: default:
throw new \InvalidArgumentException("$type is not a valid vehicle"); throw new \InvalidArgumentException("$type is not a valid vehicle");
} }

View File

@@ -2,23 +2,15 @@
namespace DesignPatterns\Creational\FactoryMethod; namespace DesignPatterns\Creational\FactoryMethod;
/**
* ItalianFactory is vehicle factory in Italy.
*/
class ItalianFactory extends FactoryMethod class ItalianFactory extends FactoryMethod
{ {
/** protected function createVehicle(string $type): VehicleInterface
* {@inheritdoc}
*/
protected function createVehicle($type)
{ {
switch ($type) { switch ($type) {
case parent::CHEAP: case parent::CHEAP:
return new Bicycle(); return new Bicycle();
break;
case parent::FAST: case parent::FAST:
return new Ferrari(); return new CarFerrari();
break;
default: default:
throw new \InvalidArgumentException("$type is not a valid vehicle"); 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 :language: php
:linenos: :linenos:
Porsche.php CarMercedes.php
.. literalinclude:: Porsche.php .. literalinclude:: CarMercedes.php
:language: php :language: php
:linenos: :linenos:
Bicycle.php CarFerrari.php
.. literalinclude:: CarFerrari.php
:language: php
:linenos:
Bicycle.php
.. literalinclude:: Bicycle.php .. literalinclude:: Bicycle.php
:language: php :language: php
:linenos: :linenos:
Ferrari.php
.. literalinclude:: Ferrari.php
:language: php
:linenos:
Test Test
---- ----

View File

@@ -6,44 +6,46 @@ use DesignPatterns\Creational\FactoryMethod\FactoryMethod;
use DesignPatterns\Creational\FactoryMethod\GermanFactory; use DesignPatterns\Creational\FactoryMethod\GermanFactory;
use DesignPatterns\Creational\FactoryMethod\ItalianFactory; use DesignPatterns\Creational\FactoryMethod\ItalianFactory;
/**
* FactoryMethodTest tests the factory method pattern.
*/
class FactoryMethodTest extends \PHPUnit_Framework_TestCase class FactoryMethodTest extends \PHPUnit_Framework_TestCase
{ {
protected $type = array( public function testCanCreateCheapVehicleInGermany()
FactoryMethod::CHEAP,
FactoryMethod::FAST,
);
public function getShop()
{ {
return array( $factory = new GermanFactory();
array(new GermanFactory()), $result = $factory->create(FactoryMethod::CHEAP);
array(new ItalianFactory()),
); $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 * @expectedException \InvalidArgumentException
* @expectedExceptionMessage spaceship is not a valid vehicle * @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; namespace DesignPatterns\Creational\FactoryMethod;
/**
* VehicleInterface is a contract for a vehicle.
*/
interface VehicleInterface interface VehicleInterface
{ {
/** public function setColor(string $rgb);
* sets the color of the vehicle.
*
* @param string $rgb
*/
public function setColor($rgb);
} }