构造器模式 目的 构造器 Builder 是一个构建复杂对象元件的接口。
有时,如果构造器对它所构建的东西有更好的了解,这个接口也可以是一个拥有默认方法的抽象类(也就是适配器)。
如果你的对象有一个复杂的继承树,那么,从逻辑上讲,构造器也对应有一个复杂的继承树。
注:构造器通常提供一个流式接口,参见 PHPUnit 的模拟构造器为例。
使用场景
UML 类图
代码 Director.php 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?php declare (strict_types = 1 );namespace DesignPatterns \Creational \Builder ;use DesignPatterns \Creational \Builder \Parts \Vehicle ;class Director { public function build (Builder $builder ): Vehicle { $builder ->createVehicle (); $builder ->addDoors (); $builder ->addEngine (); $builder ->addWheel (); return $builder ->getVehicle (); } }
Builder.php 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?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 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 <?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 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 <?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 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?php declare (strict_types = 1 );namespace DesignPatterns \Creational \Builder \Parts ;abstract class Vehicle { private array $data = []; public function setPart (string $key , object $value ) { $this ->data[$key ] = $value ; } }
Parts/Truck.php 1 2 3 4 5 6 7 <?php declare (strict_types = 1 );namespace DesignPatterns \Creational \Builder \Parts ;class Truck extends Vehicle {}
Parts/Car.php 1 2 3 4 5 6 7 <?php declare (strict_types = 1 );namespace DesignPatterns \Creational \Builder \Parts ;class Car extends Vehicle {}
Parts/Engine.php 1 2 3 4 5 6 7 <?php declare (strict_types = 1 );namespace DesignPatterns \Creational \Builder \Parts ;class Engine {}
Parts/Wheel.php 1 2 3 4 5 6 7 <?php declare (strict_types = 1 );namespace DesignPatterns \Creational \Builder \Parts ;class Wheel {}
Parts/Door.php 1 2 3 4 5 6 7 <?php declare (strict_types = 1 );namespace DesignPatterns \Creational \Builder \Parts ;class Door {}
测试 Tests/DirectorTest.php 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <?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 ); } }