首頁 >後端開發 >php教程 >深入淺析PHP中的建造者模式

深入淺析PHP中的建造者模式

青灯夜游
青灯夜游轉載
2021-07-19 19:51:232634瀏覽

在先前的文章《淺談PHP中的中介者模式》中我們介紹了PHP中的中介者模式,以下這篇文章帶大家了解一下PHP設計模式中的建造者模式。

深入淺析PHP中的建造者模式

建造者模式,也可以叫做生成器模式,builder這個字的原意就包含了建築者、開發者、創建者的意義。很明顯,這個模式又是一個創建型的模式,用來創造物件。那麼它的特點是什麼呢?從建築上來說,蓋房子不是一下子就馬上能把一個房子蓋好的,而是透過一磚一瓦搭建出來的。一個房子不僅有磚瓦,還有各種管道,各種電線等等,由它們各個不部分共同組成了一棟房子。可以說,建造者模式就是這樣非常形象化的由各種部件來組成一個物件(房子)的過程。

Gof類別圖及解釋

GoF定義:將一個複雜物件的建構與它的表示分離,使得同樣的建構過程可以創建不同的表示

GoF類圖

深入淺析PHP中的建造者模式

#程式碼實作

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();

最後看看我們的實現,是不是非常簡單,準備好工程隊,準備好不同的建造者,然後交給工程隊去生產就好啦! !

  • 其實這個模式要解決的最主要問題就是一個類別可能有非常多的配置、屬性,這些配置、屬性也不全是必須要配置的,一次性的實例化去配置這些東西非常麻煩。這時就可以考慮讓這些配置、屬性變成一個可隨時新增的部分。透過不同的屬性組合拿到不同的物件。
  • 上面那一條,在GoF那裡的原文是:它使你改變一個產品的內部表示;它將建構程式碼和表示程式碼分開;它使你可以對建構過程進行更精細的控制。
  • 再說簡單一點,物件太複雜,我們可以一部分一部分的拼裝它!
  • 了解一點Android開發的一定不會陌生,創建對話框物件AlterDialog.builder
  • Laravel中,資料庫元件也使用了建造者模式,你可以翻閱下原始碼中Database \Eloquent和Database\Query目錄中是否都有一個Builder.php

#大家都知道,手機組裝是一件複雜的過程,所以,不同型號的手機我們都有對應的圖紙(Builder),將圖紙和配件交給流水線上的工人(Director),他們就會根據圖紙使用配件來生產出我們所需的各種不同型號的手機(Product)。很明顯,我們都是偉大的建造者,為我們的產業添磚加瓦! ! !

完整程式碼:https://github.com/zhangyue0503/designpatterns-php/blob/master/16.builder/source/builder.php

#實例

前面說過Android有很多Dialog對話方塊都會用建造者模式來實現,身為手機工廠的老闆,客製化的Android系統也是非常重要的部分。就像X米一樣,從MIUI入手,先拿下了軟體市場,讓大家覺得這個系統非常好用,然後再開始開發手機。這就說明軟硬體的確是現代手機的兩大最重要的組成部分,缺了誰都不行。這回,我們就用建造者模式簡單的實作一套對話框元件吧!

對話方塊類別圖

深入淺析PHP中的建造者模式

#完整原始碼:https://github.com/zhangyue0503/designpatterns-php /blob/master/16.builder/source/builder-dialog.php

<?php

class Dialog
{
    private $attributes = [];
    private $buttons = [];
    private $title = &#39;&#39;;
    private $content = &#39;&#39;;

    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, &#39;显示提示框 === &#39;, PHP_EOL;
        echo &#39;标题:&#39; . $this->title, PHP_EOL;
        echo &#39;内容:&#39; . $this->content, PHP_EOL;
        echo &#39;样式:&#39; . implode(&#39;,&#39;, $this->attributes), PHP_EOL;
        echo &#39;按扭:&#39; . implode(&#39;,&#39;, $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(&#39;置于顶层&#39;);
        $builder->BuildAttribute(&#39;居中显示&#39;);

        $builder->BuildButton(&#39;确认&#39;);
        $builder->BuildButton(&#39;取消&#39;);

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

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

        $builder = new DialogBuilder();

        $builder->BuildAttribute(&#39;置于顶层&#39;);
        $builder->BuildAttribute(&#39;居中显示&#39;);
        $builder->BuildAttribute(&#39;背景庶照&#39;);
        $builder->BuildAttribute(&#39;外部无法点击&#39;);

        $builder->BuildButton(&#39;确认&#39;);
        $builder->BuildButton(&#39;取消&#39;);

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

$d1 = new DialogDirector();
$d1->Construct(&#39;窗口1&#39;, &#39;确认要执行操作A吗?&#39;)->GetDialog()->ShowDialog();

$d2 = new ModalDialogDirector();
$d2->Construct(&#39;窗口2&#39;, &#39;确认要执行操作B吗?&#39;)->GetDialog()->ShowDialog();

說明

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

原文網址:https://juejin.cn/post/6844903981836320781

作者:硬核心專案經理

#推薦學習:《PHP影片教學

以上是深入淺析PHP中的建造者模式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除