1、模式定义
简单工厂的作用是 实例化 对象,而不需要客户了解这个对象属于哪个具体的子类。简单工厂实例化的类具有相同的接口或者基类,在子类比较固定并不需要扩展时,可以使用简单工厂。
2、UML类图
3、实例代码
ConcreteFactory.php
<?php namespace DesignPatterns\Creational\SimpleFactory; /** * ConcreteFactory类 */ class ConcreteFactory { /** * @var array */ protected $ type List; /** * 你可以在这里注入自己的车子类型 */ public function __construct() { $this->typeList = array( 'bicycle' => __NAMESPACE__ . '\Bicycle', 'other' => __NAMESPACE__ . '\Scooter' ); } /** * 创建车子 * * @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(); } }
VehicleInterface.php
<?php namespace DesignPatterns\Creational\SimpleFactory; /** * VehicleInterface 是车子接口 */ interface VehicleInterface { /** * @param mixed $destination * * @return mixed */ public function driveTo($destination); }
Bicycle.php
<?php
namespace DesignPatterns\Creational\SimpleFactory;
/**
* 自行车类
*/
class Bicycle implements VehicleInterface
{
/**
* @param mixed $destination
*
* @return mixed| void
*/
public function driveTo($destination)
{
}
}
Scooter.php
<?php namespace DesignPatterns\Creational\SimpleFactory; /** * 摩托车类 */ class Scooter implements VehicleInterface { /** * @param mixed $destination */ public function driveTo($destination) { } }
4、测试代码
Tests/SimpleFactoryTest.php
<?php
namespace DesignPatterns\Creational\SimpleFactory\Tests;
use DesignPatterns\Creational\SimpleFactory\ConcreteFactory;
/**
* SimpleFactoryTest 用于测试 简单工厂模式
*/
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\Creational\SimpleFactory\VehicleInterface', $obj);
}
/**
* @expectedException \InvalidArgumentException
*/
public function testBadType()
{
$this->factory->createVehicle('car');
}
}
5、总结
采用简单工厂的优点是可以使用户根据参数获得对应的类实例,避免了直接实例化类,降低了耦合性;缺点是可实例化的类型在编译期间已经被确定,如果增加新类型,则需要修改工厂,不符合OCP(开闭原则)的原则。简单工厂需要知道所有要生成的类型,当子类过多或者子类层次过多时不适合使用。