PHP和golang实现设计模式-建造者模式

建造者模式:是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
比方说造房子,房子有各种各样的,但是主要流程基本一样,圈地,打地基,砌墙,装修,基本上所有房子都是一样的流程。建造者模式的本质和建造楼房是一致的:即流程不变,但每个流程实现的具体细节则是经常变化的。建造者模式的好处就是保证了流程不会变化,流程即不会增加、也不会遗漏或者产生流程次序错误,这是非常重要的。

建造者模式通常包括下面几个角色:

  1. builder:给出一个抽象接口,以规范产品对象的各个组成成分的建造。这个接口规定要实现复杂对象的哪些部分的创建,并不涉及具体的对象部件的创建。

  2. ConcreteBuilder:实现Builder接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建。 在建造过程完成后,提供产品的实例。

  3. Director:调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。

  4. 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
头:
脚:瘦子的脚
身体:瘦子的身体
手:瘦子的手