13.4建造者模式
建造者模式(Builder),又叫生成器模式,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式可以将一个产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。如果我们用了建造者模式,那么用户就只需指定需要建造的类型就可以得到它们,而具体建造的过程和细节就不需知道了。
代码结构图
代码示例
抽象建造类
abstract class PersonBuilder
{
protected $g = null;
protected $p = null;
public function __construct($g, $p)
{
$this->g = $g;
$this->p = $p;
}
abstract function BuildHead();
abstract function BuildBody();
abstract function BuildArmLeft();
abstract function BuildArmRight();
abstract function BuildLegLeft();
abstract function BuildLegRight();
}
建造小人的具体类
class PersonThinBuilder extends PersonBuilder
{
public function __construct($g, $p)
{
parent::__construct($g, $p);
}
public function BuildHead()
{
$this->g->Draw($this->p, '瘦小人的头');
}
public function BuildBody()
{
$this->g->Draw($this->p, '瘦小人的身体');
}
public function BuildArmLeft()
{
$this->g->Draw($this->p, '瘦小人的左胳膊');
}
public function BuildArmRight()
{
$this->g->Draw($this->p, '瘦小人的右胳膊');
}
public function BuildLegLeft()
{
$this->g->Draw($this->p, '瘦小人的左腿');
}
public function BuildLegRight()
{
$this->g->Draw($this->p, '瘦小人的右腿');
}
}
class PersonFatBuilder extends PersonBuilder
{
//实现方法同上
}
指挥者类
class PersonDirector
{
private $pb = null;
//用户告诉指挥者,我们需要什么样的小人
public function __construct($pb)
{
$this->pb = $pb;
}
//根据用户的选择建造小人
public function CreatePerson()
{
$this->pb->BuildHead();
$this->pb->BuildBody();
$this->pb->BuildArmLeft();
$this->pb->BuildArmRight();
$this->pb->BuildLegLeft();
$this->pb->BuildLegRight();
}
}
客户端代码
public function builderImp()
{
$g = new Graphics();
$p = new Pen('黄色');
$ptb = new PersonThinBuilder($g, $p);
$pdThin = new PersonDirector($ptb);
$pdThin->CreatePerson();
$pfb = new PersonFatBuilder($g, $p);
$pdFat = new PersonDirector($pfb);
$pdFat->CreatePerson();
}
13.5建造者模式解析
建造者模式(Builder)结构图 总结上图:
- Builder,是为创建一个Product对象的各个部件指定的抽象接口。
- ConcreteBuilder,是具体建造者,实现Builder接口,构造和装配各个部件。
- Product,是具体的产品角色。
- Director,是构建一个使用Builder接口的对象。
建造者模式的使用场景:
它主要是用于创建一些复杂的对象,这些对象内部构建间的建造顺序通常是稳定的,但对象内部的构建通常面临着复杂的变化。
建造者模式的好处就是使得建造代码与表示代码分离,由于建造者隐藏了该产品是如何组装的,所以若需要改变一个产品的内部表示,只需要再定义一个具体的建造者就可以了。
13.6建造者模式基本代码
代码示例:
Product类——产品类,由多个部件组成。
class Product
{
private $parts = array();
//添加产品部件
public function Add($part)
{
$this->parts[] = $part;
}
public function Show()
{
echo '产品 创建:' . PHP_EOL;
//列举所有产品部件
foreach ($this->parts as $value) {
echo $value . PHP_EOL;
}
}
}
Builder类——抽象建造者类,确定产品由两个部件PartA和PartB组成,并声明一个得到产品建造后结果的方法GetResult。
abstract class Builder
{
abstract function BuildPartA();
abstract function BuildPartB();
abstract function GetResult();
}
ConcreteBuilder1类——具体建造者类。
//建造具体的两个部件,是部件A和部件B
class ConcreteBuilder1 extends Builder
{
private $product = null;
public function __construct()
{
$this->product = new Product();
}
public function BuildPartA()
{
$this->product->Add('部件A');
}
public function BuildPartB()
{
$this->product->Add('部件B');
}
public function GetResult()
{
return $this->product;
}
}
ConcreteBuilder2类——具体建造者类。
//建造具体的两个部件,是部件X和部件Y
class ConcreteBuilder2 extends Builder
{
private $product = null;
public function __construct()
{
$this->product = new Product();
}
public function BuildPartA()
{
$this->product->Add('部件X');
}
public function BuildPartB()
{
$this->product->Add('部件Y');
}
public function GetResult()
{
return $this->product;
}
}
Director类——指挥者类。
//用来指挥建造过程
class Director
{
public function Construct($builder)
{
$builder->BuildPartA();
$builder->BuildPartB();
}
}
客户端代码
public function builderDemo()
{
$director = new Director();
$b1 = new ConcreteBuilder1();
$b2 = new ConcreteBuilder2();
//指挥者用ConcreteBuilder1的方法来建造产品
$director->Construct($b1);
$p1 = $b1->GetResult();
$p1->Show();
//指挥者用ConcreteBuilder2的方法来建造产品
$director->Construct($b2);
$p2 = $b2->GetResult();
$p2->Show();
}
建造者模式是在当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时适用的模式。