建造者模式:是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
比方说造房子,房子有各种各样的,但是主要流程基本一样,圈地,打地基,砌墙,装修,基本上所有房子都是一样的流程。建造者模式的本质和建造楼房是一致的:即流程不变,但每个流程实现的具体细节则是经常变化的。建造者模式的好处就是保证了流程不会变化,流程即不会增加、也不会遗漏或者产生流程次序错误,这是非常重要的。
建造者模式通常包括下面几个角色:
builder:给出一个抽象接口,以规范产品对象的各个组成成分的建造。这个接口规定要实现复杂对象的哪些部分的创建,并不涉及具体的对象部件的创建。
ConcreteBuilder:实现Builder接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建。 在建造过程完成后,提供产品的实例。
Director:调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。
Product:要创建的复杂对象。
举个栗子实现下
在游戏开发中建造小人是经常的事了,小人必须包括,头,身体,手和脚。现在系统要包括的分为胖子和瘦子,小怪又有头怪和无头鬼。
PHP实现
BuilderPattern.php
<?php
/**
* 产品类
*/
class product{
private $head;
private $foot;
private $body;
private $hand;
public function __construct(){
$this->id = uniqid();
}
public function setHead($head){
$this->head = $head;
}
public function setFoot($foot){
$this->foot = $foot;
}
public function setBody($body){
$this->body = $body;
}
public function setHand($hand){
$this->hand = $hand;
}
public function showSelf(){
echo "编号:{$this->id} \n";
echo "头:{$this->head} \n";
echo "脚:{$this->foot} \n";
echo "身体:{$this->body} \n";
echo "手臂:{$this->hand} \n\n";
}
}
/**
* 抽象建造者
*/
abstract class Builder{
abstract public function buildHead();
abstract public function buildFoot();
abstract public function buildBody();
abstract public function buildHand();
abstract public function getProduct();
}
/**
* 具体建造者(胖子)
*/
class FatPersonBuilder extends Builder{
private $product;
public function __construct(){
$this->product = new product();
}
public function buildHead(){
$this->product->setHead('胖子的头');
}
public function buildFoot(){
$this->product->setFoot('胖子的脚');
}
public function buildBody(){
$this->product->setBody('胖子的身体');
}
public function buildHand(){
$this->product->setHand('胖子的手臂');
}
public function getProduct(){
return $this->product;
}
}
/**
* 具体建造者(瘦子)
*/
class ThinPersonBuilder extends Builder{
private $product;
public function __construct(){
$this->product = new product();
}
public function buildHead(){
$this->product->setHand('瘦子的头');
}
public function buildFoot(){
$this->product->setFoot('瘦子的脚');
}
public function buildBody(){
$this->product->setBody('瘦子的身体');
}
public function buildHand(){
$this->product->setHand('瘦子的手臂');
}
public function getProduct(){
return $this->product;
}
}
/**
* 导演
*/
class Director{
//建造完整的小怪
public function getCompletePerson(Builder $builder){
$builder->buildHand();
$builder->buildBody();
$builder->buildHead();
$builder->buildFoot();
return $builder->getProduct();
}
//建造没头的小怪
public function getPersonWithoutHead(Builder $builder){
$builder->buildHand();
$builder->buildBody();
$builder->buildFoot();
return $builder->getProduct();
}
}
测试:
<?php
$director = new Director();
$fatBuilder = new FatPersonBuilder();
$completeFatPerson = $director->getCompletePerson($fatBuilder);
$completeFatPerson->showSelf();
$fatBuilder = new FatPersonBuilder();
$fatPersonWithoutHead = $director->getPersonWithoutHead($fatBuilder);
$fatPersonWithoutHead->showSelf();
$thinBuilder = new ThinPersonBuilder();
$thinCompletePerson = $director->getCompletePerson($thinBuilder);
$thinCompletePerson->showSelf();
$thinBuilder = new ThinPersonBuilder();
$thinPersonWithoutHead = $director->getPersonWithoutHead($thinBuilder);
$thinPersonWithoutHead->showSelf();
输出:
编号:5a4c38089bcdd
头:胖子的头
脚:胖子的脚
身体:胖子的身体
手臂:胖子的手臂
编号:5a4c38089bd4c
头:
脚:胖子的脚
身体:胖子的身体
手臂:胖子的手臂
编号:5a4c38089bd99
头:
脚:瘦子的脚
身体:瘦子的身体
手臂:瘦子的头
编号:5a4c38089bdde
头:
脚:瘦子的脚
身体:瘦子的身体
手臂:瘦子的手臂
Golang实现
产品 Product.go
package BuilderPattern
import (
"fmt"
"github.com/satori/go.uuid"
)
type Product struct {
id uuid.UUID
head string
body string
foot string
hand string
}
func (p *Product) ShowSelf() {
fmt.Printf("编号:%s\n", p.id)
fmt.Printf("头:%s\n", p.head)
fmt.Printf("脚:%s\n", p.foot)
fmt.Printf("身体:%s\n", p.body)
fmt.Printf("手:%s\n\n", p.hand)
}
抽象建造者 Builer.go
package BuilderPattern
type Builder interface{
buildId()
buildHead()
buildFoot()
buildBody()
buildHand()
getProduct() Product
}
胖子建造者 FatPersonBuilder.go
package BuilderPattern
import "github.com/satori/go.uuid"
/**
* 胖子建造者
*/
type FatPersonBuilder struct{
fatPerson Product
}
func (builder *FatPersonBuilder) buildHead(){
builder.fatPerson.head = "胖子的头"
}
func (builder *FatPersonBuilder) buildFoot(){
builder.fatPerson.foot = "胖子的脚"
}
func (builder *FatPersonBuilder) buildBody(){
builder.fatPerson.body = "胖子的身体"
}
func (builder *FatPersonBuilder) buildHand(){
builder.fatPerson.hand = "胖子的手"
}
func (builder *FatPersonBuilder) buildId(){
builder.fatPerson.id = uuid.NewV4()
}
func (builder *FatPersonBuilder) getProduct() Product{
return builder.fatPerson
}
瘦子建造者 ThinPersonBuilder.go
package BuilderPattern
import "github.com/satori/go.uuid"
/**
* 瘦子建造者
*/
type ThinPersonBuilder struct{
thinPerson Product
}
func (builder *ThinPersonBuilder) buildHead(){
builder.thinPerson.head = "瘦子的头"
}
func (builder *ThinPersonBuilder) buildFoot(){
builder.thinPerson.foot = "瘦子的脚"
}
func (builder *ThinPersonBuilder) buildBody(){
builder.thinPerson.body = "瘦子的身体"
}
func (builder *ThinPersonBuilder) buildHand(){
builder.thinPerson.hand = "瘦子的手"
}
func (builder *ThinPersonBuilder) buildId(){
builder.thinPerson.id = uuid.NewV4()
}
func (builder *ThinPersonBuilder) getProduct() Product{
return builder.thinPerson
}
导演 Director.go
package BuilderPattern
type Director struct{
}
// 建造完整的小人
func (director *Director) GetCompletePerson(builder Builder) Product{
builder.buildId()
builder.buildHead()
builder.buildFoot()
builder.buildBody()
builder.buildHand()
return builder.getProduct()
}
// 建造无头鬼
func (director *Director) GetPersonWithoutHead(builder Builder) Product{
builder.buildId()
builder.buildFoot()
builder.buildBody()
builder.buildHand()
return builder.getProduct()
}
测试 main.go
package main
import "BuilderPattern"
func main(){
director := new(BuilderPattern.Director)
completeFatPerson := director.GetCompletePerson(new(BuilderPattern.FatPersonBuilder))
completeFatPerson.ShowSelf()
fatPersonWithoutHead := director.GetPersonWithoutHead(new(BuilderPattern.FatPersonBuilder))
fatPersonWithoutHead.ShowSelf()
thinCompletePerson := director.GetCompletePerson(new(BuilderPattern.ThinPersonBuilder))
thinCompletePerson.ShowSelf()
thinPersonWithoutHead := director.GetPersonWithoutHead(new(BuilderPattern.ThinPersonBuilder))
thinPersonWithoutHead.ShowSelf()
}
输出:
编号:76f4c01d-e352-4fb9-8fec-ec1d61b97084
头:胖子的头
脚:胖子的脚
身体:胖子的身体
手:胖子的手
编号:7dcbfd83-b1bf-48f8-9506-d98e6eca5934
头:
脚:胖子的脚
身体:胖子的身体
手:胖子的手
编号:88637d4e-1f39-4901-91e0-bfa243f7144e
头:瘦子的头
脚:瘦子的脚
身体:瘦子的身体
手:瘦子的手
编号:b1ffdae6-2dfd-4fcf-afbd-80324f1c6275
头:
脚:瘦子的脚
身体:瘦子的身体
手:瘦子的手