【工厂模式】
工厂模式,又称工厂方法模式。说到工厂,我们可以联想到一个服装厂可以生产出各式各样的衣服,随着市场的需要,也会生产出新的款式的衣服,但是我们并不能预测新款是什么样子,设计师设计出来交给工厂安排到对应生产线上生产就完了。
在编程中与之相似的是,有时候我们在创建对象的过程中,并不能确定类一定创建(实例化)出哪一种类型的对象,我们更希望根据不同参数得到不同的类实例,这时我们可以通过定义一个父类作为定义创建对象的接口,将实例化推迟到子类中完成,让子类来决定实例化哪一个具体的对象。这样做的好处是把创建对象的过程封装了起来,通过一个工厂类来创建新的对象,而不是每创建一个对象就new一遍。
结构:1个工厂父类(interface或abstract) 、多个具体工厂子类(实现父类接口或继承抽象父类)
1个产品父类(interface或abstract) 、多个具体产品子类(实现父类接口或继承抽象父类)
示例:下面以一个服装厂生成衣服为例,服装厂有两个分厂,分别负责生产男装和女装
- 抽象工厂父类 ClothesFactory.php :
<?php
namespace app\index\controller;
//抽象父类工厂(服装总厂)
abstract class ClothesFactory
{
//要求子类(分厂)必须可以实现的方法(职能):
//生产衣服
abstract public function createClothes();
}
- 具体工厂子类1 OneFactory.php:
<?php
namespace app\index\controller;
//具体工厂(第一分厂)继承父类工厂
class OneFactory extends ClothesFactory
{
//实现父类定义的抽象方法(生产衣服的职能)
public function createClothes()
{
//第一分厂负责生产男装
return new ManClothes();
}
}
- 具体工厂子类2 TwoFactory.php:
<?php
namespace app\index\controller;
//具体工厂(第二分厂)继承父类工厂
class TwoFactory extends ClothesFactory
{
//实现父类定义的抽象方法(生产衣服的职能)
public function createClothes()
{
//第二分厂负责生产女装
return new WomanClothes();
}
}
- 抽象产品父类 Clothes.php:
<?php
namespace app\index\controller;
//抽象产品父类(所有种类衣服)
abstract class Clothes
{
//定义数量、尺码属性
protected $num;
protected $size;
public function __set($name,$value){
$this->$name = $value;
}
public function __get($name){
return $this->$name;
}
//要求子类(子产品 男装女装等)必须可以被执行的方法(操作):
//被生产
abstract public function create();
}
- 具体产品子类1 ManClothes.php :
<?php
namespace app\index\controller;
//子类产品(男装)
class ManClothes extends Clothes
{
//被生产
public function create()
{
return '男装数量:'. $this->num . ',尺码:' . $this->size;
}
}
- 具体产品子类2 WomanClothes.php :
<?php
namespace app\index\controller;
//子类产品(女装)
class WomanClothes extends Clothes
{
//被生产
public function create()
{
return '女装数量:'. $this->num . ',尺码:' . $this->size;
}
}
- 测试:
<?php
namespace app\index\controller;
class Test
{
public function test()
{
$factory = new OneFactory();
$toDo = $factory->createClothes();
$toDo->num = 1;
$toDo->size = 'xxl';
$res = $toDo->create();
var_dump($res);
}
}