PHP 生成器模式

2022-05-05 11:23 更新

目的

生成器模式(Builder,或稱建造者模式)是一個(gè)接口,用于構(gòu)建復(fù)雜對(duì)象的各個(gè)部分。

在某些情況下,如果生成器對(duì)其構(gòu)建的內(nèi)容有很好的了解,那么這個(gè)接口可以是一個(gè)抽象類,并會(huì)有一個(gè)默認(rèn)方法(也稱適配器)。

如果對(duì)象具有復(fù)雜的繼承結(jié)構(gòu),那么按照的正常邏輯,生成器也應(yīng)該有一個(gè)復(fù)雜的繼承結(jié)構(gòu)。

注意:生成器通常有都有一個(gè)完善的接口,例如 PHPUnit 的模擬生成器(Mock Builder)。

 例子

  • PHPUnit: 模擬生成器(Mock Builder)

 UML 圖

Alt Builder UML Diagram

 代碼

Director.php

<?php
declare(strict_types=1);

namespace DesignPatterns\Creational\Builder;

use DesignPatterns\Creational\Builder\Parts\Vehicle;

/**
 * Director is part of the builder pattern. It knows the interface of the builder
 * and builds a complex object with the help of the builder
 *
 * You can also inject many builders instead of one to build more complex objects
 */
class Director{
    public function build(Builder $builder): Vehicle{
        $builder->createVehicle();
        $builder->addDoors();
        $builder->addEngine();
        $builder->addWheel();

        return $builder->getVehicle();
    }
}

Builder.php

<?php
declare(strict_types=1);

namespace DesignPatterns\Creational\Builder;

use DesignPatterns\Creational\Builder\Parts\Vehicle;

interface Builder{
    public function createVehicle();
    public function addWheel();
    public function addEngine();
    public function addDoors();
    public function getVehicle(): Vehicle;
}

TruckBuilder.php

<?php
declare(strict_types=1);

namespace DesignPatterns\Creational\Builder;

use DesignPatterns\Creational\Builder\Parts\Door;
use DesignPatterns\Creational\Builder\Parts\Engine;
use DesignPatterns\Creational\Builder\Parts\Wheel;
use DesignPatterns\Creational\Builder\Parts\Truck;
use DesignPatterns\Creational\Builder\Parts\Vehicle;

class TruckBuilder implements Builder{
    private Truck $truck;
    public function addDoors(){
        $this->truck->setPart('rightDoor', new Door());
        $this->truck->setPart('leftDoor', new Door());
    }
    public function addEngine(){
        $this->truck->setPart('truckEngine', new Engine());
    }
    public function addWheel(){
        $this->truck->setPart('wheel1', new Wheel());
        $this->truck->setPart('wheel2', new Wheel());
        $this->truck->setPart('wheel3', new Wheel());
        $this->truck->setPart('wheel4', new Wheel());
        $this->truck->setPart('wheel5', new Wheel());
        $this->truck->setPart('wheel6', new Wheel());
    }
    public function createVehicle(){
        $this->truck = new Truck();
    }
    public function getVehicle(): Vehicle{
        return $this->truck;
    }
}

CarBuilder.php

<?php
declare(strict_types=1);

namespace DesignPatterns\Creational\Builder;

use DesignPatterns\Creational\Builder\Parts\Door;
use DesignPatterns\Creational\Builder\Parts\Engine;
use DesignPatterns\Creational\Builder\Parts\Wheel;
use DesignPatterns\Creational\Builder\Parts\Car;
use DesignPatterns\Creational\Builder\Parts\Vehicle;

class CarBuilder implements Builder{
    private Car $car;

    public function addDoors(){
        $this->car->setPart('rightDoor', new Door());
        $this->car->setPart('leftDoor', new Door());
        $this->car->setPart('trunkLid', new Door());
    }

    public function addEngine(){
        $this->car->setPart('engine', new Engine());
    }

    public function addWheel(){
        $this->car->setPart('wheelLF', new Wheel());
        $this->car->setPart('wheelRF', new Wheel());
        $this->car->setPart('wheelLR', new Wheel());
        $this->car->setPart('wheelRR', new Wheel());
    }

    public function createVehicle(){
        $this->car = new Car();
    }

    public function getVehicle(): Vehicle{
        return $this->car;
    }
}

Parts/Vehicle.php

<?php
declare(strict_types=1);

namespace DesignPatterns\Creational\Builder\Parts;

abstract class Vehicle{
    public function setPart(string $key, object $value){}
}

Parts/Truck.php

<?php
declare(strict_types=1);

namespace DesignPatterns\Creational\Builder\Parts;

class Truck extends Vehicle{}

Parts/Car.php

<?php
declare(strict_types=1);

namespace DesignPatterns\Creational\Builder\Parts;

class Car extends Vehicle{}

Parts/Engine.php

<?php
declare(strict_types=1);

namespace DesignPatterns\Creational\Builder\Parts;

class Engine{}

Parts/Wheel.php

<?php
declare(strict_types=1);

namespace DesignPatterns\Creational\Builder\Parts;

class Wheel{}

Parts/Door.php

<?php
declare(strict_types=1);

namespace DesignPatterns\Creational\Builder\Parts;

class Door{}

 測(cè)試

Tests/DirectorTest.php

<?php
declare(strict_types=1);

namespace DesignPatterns\Creational\Builder\Tests;

use DesignPatterns\Creational\Builder\Parts\Car;
use DesignPatterns\Creational\Builder\Parts\Truck;
use DesignPatterns\Creational\Builder\TruckBuilder;
use DesignPatterns\Creational\Builder\CarBuilder;
use DesignPatterns\Creational\Builder\Director;
use PHPUnit\Framework\TestCase;

class DirectorTest extends TestCase{
    public function testCanBuildTruck(){
        $truckBuilder = new TruckBuilder();
        $newVehicle = (new Director())->build($truckBuilder);

        $this->assertInstanceOf(Truck::class, $newVehicle);
    }

    public function testCanBuildCar(){
        $carBuilder = new CarBuilder();
        $newVehicle = (new Director())->build($carBuilder);

        $this->assertInstanceOf(Car::class, $newVehicle);
    }
}


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)