PHP设计模式(五)之建造者模式
一、什么是建造者模式
**定义:**建造者模式(Builder Pattern)又称生成器模式,是一种构建对象的模式。
1)它可以将一个产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。
2)由于建造零件的过程很复杂,因此,这些零件的建造过程往往被“外部化”到另一个乘坐建造者的对象里,建造者对象返还给客户端的是一个全部零件都建造完毕的产品对象。它将产品的结构和建造过程对客户端隐藏起来。
【释义】
使用生活中的例子来接近建造者模式
1)去餐馆吃饭,点个辣子鸡,A店可能辣一点,B店可能淡一点,每一家店都有自己的做法,因此也就有不同的味道,所以就有了好吃与否的问题。
2)快餐店,KFC,德克士...无论在哪个城市的哪家店,它们的味道与做法都是一样的,用户只需要下订单就能吃到了。
二、建造者模式的四种角色
Builder:抽象构造者类,为创建一个Product对象的各个部件指定抽象接口。
ConcreteBuilder:具体构造者类,实现Builder的接口以构造和装配该产品的各个部件。定义并明确它所创建的表示。提供一个检索产品的接口
**Director:指挥者,**构造一个使用Builder接口的对象。
**Product:表示被构造的复杂对象。**ConcreateBuilder创建该产品的内部表示并定义它的装配过程。
三、建造者模式的使用场景
使用场景:一些基本的部件不会改变,而其它组合经常发生变化的时候。
四、建造者模式优缺点
优点:
- 每个具体构建者相互独立,利于系统扩展
- 客户端不必知道产品内部细节,利于细节风险控制;
- 建造者模式比较独立,将对象本身与构建过程解耦
- 精准控制构建出的对象和内容,构造层和显示层是分离的
缺点:
- 产品的组成部分必须相同,这限制了其使用范围。
- 如果产品的内部变化复杂,该模式会增加很多的建造者类。
五、建造者模式与工厂模式的区别
1)与抽象工厂模式相比,建造者模式返回一个组装好的完整产品,而抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族 。
2)在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中,客户端可以不直接调用建造者的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象 。
3)如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车
总结:建造者模式更关注于零件装配的顺序
六、代码实现
AbstractBuilder.php
<?php
/**
* 抽象豆腐构造者类 => 对应Builder
*/
abstract class AbstractBuilder
{
// 存储具体产品实例对象
protected $toFu;
public abstract function buildStep1();
public abstract function buildStep2();
public abstract function buildStep3();
public abstract function getToFu();
}
ToFu.php
<?php
/**
* 具体实体,豆腐产品角色 => 对应Product
*/
class ToFu
{
// 做豆腐的三个步骤
protected $step1;
protected $step2;
protected $step3;
public function setStep1($str)
{
$this->step1 = $str;
}
public function setStep2($str)
{
$this->step2 = $str;
}
public function setStep3($str)
{
$this->step3 = $str;
}
public function showToFu()
{
echo '新鲜美味的豆腐有三个步骤:' . $this->step1 . $this->step2 . $this->step3;
}
}
CreateBuilderToFu.php // 新鲜豆腐构造者
<?php
/**
* 具体豆腐产品角色构造者类 =》 对应 ConcreteBuilder
*/
class CreateBuilderToFu extends AbstractBuilder
{
public function __construct()
{
// 实例化具体产品
$this->toFu = new ToFu();
}
// 制作豆腐的第一步
public function buildStep1()
{
$this->toFu->setStep1('第一步');
}
// 制作豆腐的第二步
public function buildStep2()
{
$this->toFu->setStep2('第二步');
}
// 制作豆腐的第三步
public function buildStep3()
{
$this->toFu->setStep3('第三步');
}
// 新鲜的豆腐
public function getToFu()
{
return $this->toFu;
}
}
CreateBuilderMaPoToFu.php // 麻婆豆腐构造者
<?php
/**
* 具体豆腐产品角色构造者类 =》 对应 ConcreteBuilder
*/
class CreateBuilderMaPoToFu extends AbstractBuilder
{
public function __construct()
{
$this->toFu = new ToFu();
}
// 制作豆腐的第一步
public function buildStep1()
{
$this->toFu->setStep1('麻婆豆腐的做法:第一步,准备豆腐,切小块,并准备配料~~~~');
}
// 制作豆腐的第二步
public function buildStep2()
{
$this->toFu->setStep2('麻婆豆腐的做法:第二步,入锅翻炒~~~');
}
// 制作豆腐的第三步
public function buildStep3()
{
$this->toFu->setStep3('麻婆豆腐的做法:第三步,客观,你的四川麻婆豆腐做好了~~~');
}
// 获取麻婆豆腐
public function getToFu()
{
return $this->toFu;
}
}
Director.php
<?php
/**
* 产品指挥者 =》 对应 Director
*/
class Director
{
public $build;
public function setBuilder(AbstractBuilder $builder)
{
$this->build = $builder;
}
public function startBuild()
{
$this->build->buildStep1();
$this->build->buildStep2();
$this->build->buildStep3();
return $this->build->getToFu();
}
}
index.php
<?php
require_once './AbstractBuilder.php';
require_once './CreateBuilderToFu.php';
require_once './CreateBuilderMaPoToFu.php';
require_once './ToFu.php';
require_once './Director.php';
// 实例化指挥着
$director = new Director();
// 通过产品角色构造者生产新鲜豆腐
$toFuBuilder = new CreateBuilderToFu();
$director->setBuilder($toFuBuilder);
$newToFu = $director->startBuild();
$newToFu->showToFu();
// 通过产品角色构造者生产麻婆豆腐
$maPoToFu = new CreateBuilderMaPoToFu();
$director->setBuilder($maPoToFu);
$director->startBuild()->showToFu();
我是夕阳何处寻,期待和优秀的你一起同行!
夕阳何处寻
2019年12月25日