初学设计模式之建造者模式
建造者模式定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
从故事开始
老高:最近我在练习拼乐高,看我拼的乐高怎么样
老摸动了一下乐高模型
轰~~乐高模型散架了
老摸:你拼的也不咋地呀
老高:这不刚开始总是忘放一些零件
老摸:我写个程序帮你
用代码描述故事
创建乐高小人
<?php
namespace Builder\Elementary;
class PersonBuilder
{
public function head()
{
return "记得创建头部";
}
public function body()
{
return "记得创建身体";
}
public function armLeft()
{
return "记得创建左手";
}
public function armRight()
{
return "记得创建右手";
}
public function legLeft()
{
return "记得创建左腿";
}
public function rightLeft()
{
return "记得创建右腿";
}
}
新问题
老高:你这个代码不行呀,我想拼两个种族,一个是左胳膊长的,一个是右胳膊长的,你这么写我拼到后面又忘记加长胳膊了
老摸:原来那个难看的模型是你故意拼的呀
新问题解决的代码
抽象一个建造人的类(防止老高忘记小人的零件:规定建造方法)
abstract class PersonBuilder
{
abstract public function buildHead();
abstract public function buildBody();
abstract public function buildArmLeft();
abstract public function buildArmRight();
abstract public function buildLegLeft();
abstract public function buildLegRight();
}
左手长小人的建造方法
class ArmLeftLong extends PersonBuilder
{
public function buildHead()
{
return "记得创建头部";
}
public function buildBody()
{
return "记得创建身体";
}
public function buildArmLeft()
{
return "记得创建左手长一点";
}
public function buildArmRight()
{
return "记得创建右手";
}
public function buildLegLeft()
{
return "记得创建左腿";
}
public function buildLegRight()
{
return "记得创建右腿";
}
}
右手长小人的建造方法
class ArmRightLong extends PersonBuilder
{
public function buildHead()
{
return "记得创建头部";
}
public function buildBody()
{
return "记得创建身体";
}
public function buildArmLeft()
{
return "记得创建左手";
}
public function buildArmRight()
{
return "记得创建右手长一点";
}
public function buildLegLeft()
{
return "记得创建左腿";
}
public function buildLegRight()
{
return "记得创建右腿";
}
}
注入灵魂(建造模式的灵魂:指挥者类)
class Director
{
public $builder;
public function __construct(PersonBuilder $builder)
{
$this->builder = $builder;
}
public function createPerson()
{
$head = $this->builder->buildHead();
$body = $this->builder->buildBody();
$armLeft = $this->builder->buildArmLeft();
$armRight = $this->builder->buildArmRight();
$legLeft = $this->builder->buildLegLeft();
$legRight = $this->builder->buildLegRight();
return $head + $body + $armLeft + $armRight + $legLeft + $legRight;
}
}
提醒老高如何创建乐高小人(实际控制器中调用)
class Controller
{
public function step()
{
$leGao1Builder = new ArmLeftLong();
$leGao1 = (new Director($leGao1Builder))->createPerson();
$leGao2Builder = new ArmRightLong();
$leGao2 = (new Director($leGao2Builder))->createPerson();
$leGao3Builder = new ArmRightLong();
$leGao3 = (new Director($leGao3Builder))->createPerson();
return $leGao1 + $leGao2 + $leGao3;
}
}
总结
仔细分析上面的故事会发现,老高的创建小人的过程是稳定的,但是需要建造的具体细节不通,有的小人左胳膊需要长,有的小人右胳膊需要长。
建造者模式好处就是:用户只需要告诉程序我想建造的类型,而具体的细节和过程用户不需要知道
什么时候使用
当创建复杂对象的算法,应该独立于该对象的组成部分以及他们的装配方式时使用建造者模式