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