PHP設計模式之建造者模式

PHP設計模式之建造者模式

建造者模式,也能夠叫作生成器模式,builder這個詞的原意就包含了建築者、開發者、建立者的含義。很明顯,這個模式又是一個建立型的模式,用來建立對象。那麼它的特色是什麼呢?從建築上來講,蓋房子不是一會兒就立刻能把一個房子蓋好的,而是經過一磚一瓦搭建出來的。一個房子不只有磚瓦,還有各類管道,各類電線等等,由它們各個不部分共同組成了一棟房子。能夠說,建造者模式就是這樣很是形象的由各類部件來組成一個對象(房子)的過程。php

Gof類圖及解釋

GoF定義:將一個複雜對象的構建與它的表示分離,使得一樣的構建過程能夠建立不一樣的表示git

GoF類圖github

建造者模式

代碼實現數據庫

class Product {
    private $parts = [];

    public function Add(String $part): void {
        $this->parts[] = $part;
    }

    public function Show(): void {
        echo PHP_EOL . '產品建立 ----', PHP_EOL;
        foreach ($this->parts as $part) {
            echo $part, PHP_EOL;
        }
    }
}
複製代碼

產品類,你能夠把它想象成咱們要建造的房子。這時的房子尚未任何內容,咱們須要給它添磚加瓦。設計模式

interface Builder {
    public function BuildPartA(): void;
    public function BuildPartB(): void;
    public function GetResult(): Product;
}

class ConcreteBuilder1 implements Builder {
    private $product;

    public function __construct() {
        $this->product = new Product();
    }

    public function BuildPartA(): void {
        $this->product->Add('部件A');
    }
    public function BuildPartB(): void {
        $this->product->Add('部件B');
    }
    public function GetResult(): Product {
        return $this->product;
    }
}

class ConcreteBuilder2 implements Builder {
    private $product;

    public function __construct() {
        $this->product = new Product();
    }

    public function BuildPartA(): void {
        $this->product->Add('部件X');
    }
    public function BuildPartB(): void {
        $this->product->Add('部件Y');
    }
    public function GetResult(): Product {
        return $this->product;
    }
}
複製代碼

建造者抽象及其實現。不一樣的開發商總會選用不一樣的品牌材料,這裏咱們有了兩個不一樣的開發商,但他們的目的一致,都是爲了去蓋房子(Product)。架構

class Director {
    public function Construct(Builder $builder) {
        $builder->BuildPartA();
        $builder->BuildPartB();
    }
}
複製代碼

構造器,用來調用建造者進行生產。沒錯,就是咱們的工程隊。它來選取材料並進行建造。一樣的工程隊,能夠接不一樣的單,但蓋出來的都是房子。只是這個房子的材料和外觀不一樣,大致上的手藝仍是共通的。框架

$director = new Director();
$b1 = new ConcreteBuilder1();
$b2 = new ConcreteBuilder2();

$director->Construct($b1);
$p1 = $b1->getResult();
$p1->Show();

$director->Construct($b2);
$p2 = $b2->getResult();
$p2->Show();

複製代碼

最後看看咱們的實現,是否是很是簡單,準備好工程隊,準備好不一樣的建造者,而後交給工程隊去生產就好啦!!ui

  • 其實這個模式要解決的最主要問題就是一個類可能有很是多的配置、屬性,這些配置、屬性也並不全是必需要配置的,一次性的實例化去配置這些東西很是麻煩。這時就能夠考慮讓這些配置、屬性變成一個一個可隨時添加的部分。經過不一樣的屬性組合拿到不一樣的對象。
  • 上面那一條,在GoF那裏的原文是:它使你改變一個產品的內部表示;它將構造代碼和表示代碼分開;它使你能夠對構造過程進行更精細的控制。
  • 再說得簡單一點,對象太複雜,咱們能夠一部分一部分的拼裝它!
  • 瞭解過一點Android開發的必定不會陌生,建立對話框對象AlterDialog.builder
  • Laravel中,數據庫組件也使用了建造者模式,你能夠翻看下源碼中Database\Eloquent和Database\Query目錄中是否都有一個Builder.php

你們都知道,手機組裝是一件複雜的過程,因而,不一樣型號的手機咱們都有對應的圖紙(Builder),將圖紙和配件交給流水線上的工人(Director),他們就會根據圖紙使用配件來生產出咱們所須要的各類不一樣型號的手機(Product)。很明顯,咱們都是偉大的建造者,爲咱們的產業添磚加瓦!!!this

完整代碼:github.com/zhangyue050…spa

實例

前面說過Android中有不少Dialog對話框都會用建造者模式來實現,做爲一家手機廠的老闆,定製化的Android系統也是很是重要的一個部分。就像X米同樣,從MIUI入手,先拿下了軟件市場,讓你們以爲這個系統很是好用,而後再開始開發手機。這就說明軟硬件的確是現代手機的兩大最重要的組成部分,缺了誰都不行。這回,咱們就用建造者模式簡單的實現一套對話框組件吧!

對話框類圖

對話框功能建造者模式版

完整源碼:github.com/zhangyue050…

<?php

class Dialog {
    private $attributes = [];
    private $buttons = [];
    private $title = '';
    private $content = '';

    public function AddAttributes($attr) {
        $this->attributes[] = $attr;
    }
    public function AddButtons($button) {
        $this->buttons[] = $button;
    }
    public function SetTitle($title) {
        $this->title = $title;
    }
    public function SetContent($content) {
        $this->content = $content;
    }

    public function ShowDialog(){
        echo PHP_EOL, '顯示提示框 === ', PHP_EOL;
        echo '標題:' . $this->title, PHP_EOL;
        echo '內容:' . $this->content, PHP_EOL;
        echo '樣式:' . implode(',', $this->attributes), PHP_EOL;
        echo '按扭:' . implode(',', $this->buttons), PHP_EOL;
    }
}

interface Builder {
    public function BuildAttribute($attr);
    public function BuildButton($button);
    public function BuildTitle($title);
    public function BuildContent($content);
    public function GetDialog();
}

class DialogBuilder implements Builder{
    private $dialog;
    public function __construct(){
        $this->dialog = new Dialog();
    }
    public function BuildAttribute($attr){
        $this->dialog->AddAttributes($attr);
    }
    public function BuildButton($button){
        $this->dialog->AddButtons($button);
    }
    public function BuildTitle($title){
        $this->dialog->SetTitle($title);
    }
    public function BuildContent($content){
        $this->dialog->SetContent($content);
    }
    public function GetDialog(){
        return $this->dialog;
    }
}

class DialogDirector {
    public function Construct($title, $content){

        $builder = new DialogBuilder();

        $builder->BuildAttribute('置於頂層');
        $builder->BuildAttribute('居中顯示');

        $builder->BuildButton('確認');
        $builder->BuildButton('取消');

        $builder->BuildTitle($title);
        $builder->BuildContent($content);
        
        return $builder;
    }
}

class ModalDialogDirector {
    public function Construct($title, $content){

        $builder = new DialogBuilder();

        $builder->BuildAttribute('置於頂層');
        $builder->BuildAttribute('居中顯示');
        $builder->BuildAttribute('背景庶照');
        $builder->BuildAttribute('外部沒法點擊');

        $builder->BuildButton('確認');
        $builder->BuildButton('取消');

        $builder->BuildTitle($title);
        $builder->BuildContent($content);
        
        return $builder;
    }
}

$d1 = new DialogDirector();
$d1->Construct('窗口1', '確認要執行操做A嗎?')->GetDialog()->ShowDialog();

$d2 = new ModalDialogDirector();
$d2->Construct('窗口2', '確認要執行操做B嗎?')->GetDialog()->ShowDialog();


複製代碼

說明

  • 這回咱們的產品就有點複雜了,有標題、內容、屬性、按扭等
  • 建造過程其實都同樣,但這裏咱們主要使用了不一樣的構造器。普通對話框外面的東西是能夠點擊的,而模態窗口通常會有遮罩層,就是背景變成透明黑,並且外面的東西是不能再點擊的
  • 若是每次都直接經過構造方法去實例化窗口類,那要傳遞的參數會不少,而如今這樣,咱們就能夠經過建造者來進行組合,讓對象具備多態的效果,可以呈現不一樣的形態及功能

下期看點

建造者模式真的很是經常使用,雖然說咱們日常寫的代碼中可能用得比較少,但在不少框架或者大型系統的架構中都會有它的身影。咱們但願類都是簡單的,小巧的,但大型類的出現老是不可避免的,這個時候,建造者模式就能發揮它的做用,讓咱們可以輕鬆的構建複雜、大型的對象。好吧,不要忘了咱們的文章還在繼續,若是喜歡的話要記得關注公衆號或者掘金主頁哦,若是怕忘了,不妨寫個備忘錄哦。

相關文章
相關標籤/搜索