生成器模式(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)。
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{}
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);
}
}
更多建議: