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


复制代码

说明

  • 这回咱们的产品就有点复杂了,有标题、内容、属性、按扭等
  • 建造过程其实都同样,但这里咱们主要使用了不一样的构造器。普通对话框外面的东西是能够点击的,而模态窗口通常会有遮罩层,就是背景变成透明黑,并且外面的东西是不能再点击的
  • 若是每次都直接经过构造方法去实例化窗口类,那要传递的参数会不少,而如今这样,咱们就能够经过建造者来进行组合,让对象具备多态的效果,可以呈现不一样的形态及功能

下期看点

建造者模式真的很是经常使用,虽然说咱们日常写的代码中可能用得比较少,但在不少框架或者大型系统的架构中都会有它的身影。咱们但愿类都是简单的,小巧的,但大型类的出现老是不可避免的,这个时候,建造者模式就能发挥它的做用,让咱们可以轻松的构建复杂、大型的对象。好吧,不要忘了咱们的文章还在继续,若是喜欢的话要记得关注公众号或者掘金主页哦,若是怕忘了,不妨写个备忘录哦。

相关文章
相关标签/搜索