the REAL factory method pattern

This commit is contained in:
Trismegiste 2013-05-10 21:09:55 +02:00
parent 9b7330795d
commit cc765bde41
8 changed files with 235 additions and 0 deletions

20
FactoryMethod/Bicycle.php Normal file
View File

@ -0,0 +1,20 @@
<?php
/*
* DesignPatternPHP
*/
namespace DesignPatterns\FactoryMethod;
/**
* Bicycle is a bicycle
*/
class Bicycle implements Vehicle
{
public function setColor($rgb)
{
}
}

View File

@ -0,0 +1,45 @@
<?php
/*
* DesignPatternPHP
*/
namespace DesignPatterns\FactoryMethod;
/**
* FactoryMethod is a factory method. The good point on the SimpleFactory
* is you can subclass it to implement different way to create vehicle for
* each country.
*
* For simple case, this abstracct class could be just an interface
*/
abstract class FactoryMethod
{
/**
* 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 Vehicle a new vehicle
*/
abstract protected function createVehicle($type);
/**
* Creates a new vehicle
*
* @param string $type
*
* @return Vehicle a new vehicle
*/
public function create($type)
{
$obj = $this->createVehicle($type);
$obj->setColor("#f00");
return $obj;
}
}

20
FactoryMethod/Ferrari.php Normal file
View File

@ -0,0 +1,20 @@
<?php
/*
* DesignPatternPHP
*/
namespace DesignPatterns\FactoryMethod;
/**
* Ferrari is a italian car
*/
class Ferrari implements Vehicle
{
public function setColor($rgb)
{
}
}

View File

@ -0,0 +1,32 @@
<?php
/*
* DesignPatternPHP
*/
namespace DesignPatterns\FactoryMethod;
/**
* GermanFactory is vehicle factory in Germany
*/
class GermanFactory extends FactoryMethod
{
/**
* @inheritdoc
*/
protected function createVehicle($type)
{
switch ($type) {
case 'cheap' :
return new Bicycle();
break;
case 'fast' :
return new Porsche();
break;
default :
throw new \InvalidArgumentException("$type is not a valid vehicle");
}
}
}

View File

@ -0,0 +1,32 @@
<?php
/*
* DesignPatternPHP
*/
namespace DesignPatterns\FactoryMethod;
/**
* ItalianFactory is vehicle factory in Italy
*/
class ItalianFactory extends FactoryMethod
{
/**
* @inheritdoc
*/
protected function createVehicle($type)
{
switch ($type) {
case 'cheap' :
return new Bicycle();
break;
case 'fast' :
return new Ferrari();
break;
default :
throw new \InvalidArgumentException("$type is not a valid vehicle");
}
}
}

20
FactoryMethod/Porsche.php Normal file
View File

@ -0,0 +1,20 @@
<?php
/*
* DesignPatternPHP
*/
namespace DesignPatterns\FactoryMethod;
/**
* Porsche is a german car
*/
class Porsche implements Vehicle
{
public function setColor($rgb)
{
}
}

16
FactoryMethod/Vehicle.php Normal file
View File

@ -0,0 +1,16 @@
<?php
/*
* DesignPatternPHP
*/
namespace DesignPatterns\FactoryMethod;
/**
* Vehicle is a contract for a vehicle
*/
interface Vehicle
{
function setColor($rgb);
}

View File

@ -0,0 +1,50 @@
<?php
/*
* DesignPatternPHP
*/
namespace DesignPatterns\Tests\FactoryMethod;
use DesignPatterns\FactoryMethod;
/**
* FactoryMethodTest tests the factory method pattern
*/
class FactoryMethodTest extends \PHPUnit_Framework_TestCase
{
protected $type = array('cheap', 'fast');
public function getShop()
{
return array(
array(new FactoryMethod\GermanFactory()),
array(new FactoryMethod\ItalianFactory())
);
}
/**
* @dataProvider getShop
*/
public function testCreation(FactoryMethod\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\Vehicle', $vehicle);
}
}
/**
* @dataProvider getShop
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage spaceship is not a valid vehicle
*/
public function testUnknownType(FactoryMethod\FactoryMethod $shop)
{
$shop->create('spaceship');
}
}