1. 程式人生 > >PHP設計模式(三)——建造者模式(Builder Pattern)

PHP設計模式(三)——建造者模式(Builder Pattern)

@[TOC](PHP設計模式(三)——建造者模式(Builder Pattern))

建造者模式(Builder Pattern):將一個複雜物件的構建與它的表示分離,使得同樣的構建過程可以建立不同的表示。
建造者模式是一步一步建立一個複雜的物件,它允許使用者只通過指定複雜物件的型別和內容就可以構建它們,使用者不需要知道內部的具體構建細節。建造者模式屬於物件建立型模式。根據中文翻譯的不同,建造者模式又可以稱為生成器模式。

(一)為什麼需要建造者模式
1,物件的生產需要複雜的初始化,比如給一大堆類成員屬性賦初值,設定一下其他的系統環境變數。使用建造者模式可以將這些初始化工作封裝起來。
2,物件的生成時可根據初始化的順序或資料不同,而生成不同角色。

(二)模式應用
在很多遊戲軟體中,地圖包括天空、地面、背景等組成部分,人物角色包括人體、服裝、裝備等組成部分,可以使用建造者模式對其進行設計,通過不同的具體建造者建立不同型別的地圖或人物

(三)設計例項
如果我們想創造出有一個person類,我們通過例項化時設定的屬性不同,讓他們兩人一個是速度快的小孩,一個是知識深的長者

<?php

// 建造者資訊規格 (擺件規格資訊)
class person
{
    public $age;
    public $speed;
    public $knowledge;
}

// 抽象建造者類(擺件造模)
abstract class Builder
{
    public $_person;

    public abstract function setAge();

    public abstract function setSpeed();

    public abstract function setKnowledge();

    public function __construct(Person $person)
    {
        $this->_person = $person;
    }

    public function getPerson()
    {
        return $this->_person;
    }
}

// 長者建造者 (擺件1規格)
class OlderBuilder extends Builder
{
    public function setAge()
    {
        $this->_person->age = 70;
    }

    public function setSpeed()
    {
        $this->_person->speed = 'low';
    }

    public function setKnowledge()
    {
        $this->_person->knowledge = 'more';
    }
}

// 長者建造者(擺件2規格)
class ChildBuilder extends Builder
{
    public function setAge()
    {
        $this->_person->age = 10;
    }

    public function setSpeed()
    {
        $this->_person->speed = 'fast';
    }

    public function setKnowledge()
    {
        $this->_person->knowledge = 'litte';
    }
}

// 建築指揮官 (造擺件的人)
class Director
{
    private $_builder;

    public function __construct(Builder $builder)
    {
        $this->_builder = $builder;
    }

    public function built()
    {
        $this->_builder->setAge();
        $this->_builder->setSpeed();
        $this->_builder->setKnowledge();
    }
}

// 例項化 長者建造者
$oldB = new OlderBuilder(new Person);
// 例項化一個建造指揮官
$director = new Director($oldB);
// 指揮官建造
$director->built();
// 得到長者
$older = $oldB->getPerson();
var_dump($older);

(五)總結
使用建造者模式時,我們把建立一個person例項的過程分為了兩步.

一步是先交給對應角色的建造者,如長者建造者。這樣的好處就把角色的屬性設定封裝了起來,我們不用在new一個person時,因為要得到一個older角色的例項,而在外面寫了一堆$older->age=70。

另一步是交給了一個建造指揮者,調了一個built方法,通過先設定age,再設定Speed的順序,初始化這個角色。當然在這個例子中,初始化的順序,是無所謂的。但是如果對於一個建造漢堡,或是地圖,初始化的順序不同,可能就會得到不同的結果。

也許,你會說,我直接設定也很方便呀。是的,對於某些情況是這樣的。但是如果你考慮,我現在想增加一個青年人角色呢?如果我現在想讓建造有初始化有三種不同的順序呢?

如果你使用了建造者模式,這兩個問題就簡單了,增加一個青年人角色,那就增加一個青年年建造者類。初始化三種不同的順序,那麼就在指揮建造者中增加兩種建造方法。