乐趣区

关于php:PHP设计模式之建造者模式

建造者模式,也能够叫做生成器模式,builder 这个词的原意就蕴含了建筑者、开发者、创建者的含意。很显著,这个模式又是一个创立型的模式,用来创建对象。那么它的特点是什么呢?从修建上来说,盖房子不是一下子就马上能把一个房子盖好的,而是通过一砖一瓦搭建进去的。一个房子不仅有砖瓦,还有各种管道,各种电线等等,由它们各个不局部独特组成了一栋房子。能够说,建造者模式就是这样十分形象的由各种部件来组成一个对象(房子)的过程。

Gof 类图及解释

GoF 定义:将一个简单对象的构建与它的示意拆散,使得同样的构建过程能够创立不同的示意

GoF 类图

代码实现

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 动手,先拿下了软件市场,让大家感觉这个零碎十分好用,而后再开始开发手机。这就阐明软硬件确实是古代手机的两大最重要的组成部分,缺了谁都不行。这回,咱们就用建造者模式简略的实现一套对话框组件吧!

对话框类图

残缺源码:https://github.com/zhangyue0503/designpatterns-php/blob/master/16.builder/source/builder-dialog.php

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

阐明

  • 这回咱们的产品就有点简单了,有题目、内容、属性、按扭等
  • 建造过程其实都一样,但这里咱们次要应用了不同的结构器。一般对话框里面的货色是能够点击的,而模态窗口个别会有遮罩层,就是背景变成通明黑,而且里面的货色是不能再点击的
  • 如果每次都间接通过构造方法去实例化窗口类,那要传递的参数会很多,而当初这样,咱们就能够通过建造者来进行组合,让对象具备多态的成果,可能出现不同的状态及性能

下期看点

建造者模式真的十分罕用,虽说咱们平时写的代码中可能用得比拟少,但在很多框架或者大型零碎的架构中都会有它的身影。咱们心愿类都是简略的,玲珑的,但大型类的呈现总是不可避免的,这个时候,建造者模式就能施展它的作用,让咱们可能轻松的构建简单、大型的对象。好吧,不要忘了咱们的文章还在持续,如果喜爱的话要记得关注公众号或者掘金主页哦,如果怕忘了,无妨写个 备忘录 哦。

各自媒体平台均可搜寻【硬核项目经理】

退出移动版