![](https://webmobtuts.com/wp-content/uploads/2018/12/Demonstrating-Builder-Design-Pattern-in-PHP-800x400.jpg)
One of the other design patterns is the Builder Pattern and this pattern belongs to the Creational patterns that is used to create objects in addition to that it will prepare the object for the application too.
Builder Pattern
From wikipedia the builder pattern:
The intent of the Builder design pattern is to separate the construction of a complex object from its representation
In other terms unlike the traditional creational patterns like Factory and Singletoon, which tend to create a new empty instance of the object, the Builder create a fully prepared object ready for specific task.An example of this is to create a setup engine for specific software.
So the problem is we need a way to create an object with a set of functions already prepared, let’s see an example, imagine we have a Vehicle class and we need to create different implementations of this class using the builder pattern.
A typical Builder consists of:
- Concrete class
- A builder interface
- The different builder implementations
- A director class that calls the appropriate builder and return it.
Concrete class (Vehicle)
<?php // Concrete Class class Vehicle { public $model; public $enginesCount; public $type; const CAR = "Car"; const BUS = "Bus"; const TRAILER = "Trailer"; public function __construct() { } }
Builder interface
// Builder interface interface VehicleBuilderInterface { public function setModel(); public function setEnginesCount(); public function setType(); public function getVehicle(); }
As shown in the above code the Builder interface contains methods for preparing the builder when created and method getVehicle will return the final object.
Builder implementations
// Builder implementations class KiaCarBuilder implements VehicleBuilderInterface { private $vehicle; public function __construct(Vehicle $vehicle) { $this->vehicle = $vehicle; } public function setModel() { $this->vehicle->model = "Kia"; } public function setEnginesCount() { $this->vehicle->enginesCount = 1; } public function setType() { $this->vehicle->type = Vehicle::CAR; } public function getVehicle() { return $this->vehicle; } } class BmwBusBuilder implements VehicleBuilderInterface { private $vehicle; public function __construct(Vehicle $vechile) { $this->vehicle = $vechile; } public function setModel() { $this->vehicle->model = "Bmw"; } public function setEnginesCount() { $this->vehicle->enginesCount = 2; } public function setType() { $this->vehicle->type = Vehicle::BUS; } public function getVehicle() { return $this->vehicle; } } class ShevroletTrailerBuilder implements VehicleBuilderInterface { private $vehicle; public function __construct(Vehicle $vechile) { $this->vehicle = $vechile; } public function setModel() { $this->vehicle->model = "Shevrolet"; } public function setEnginesCount() { $this->vehicle->enginesCount = 2; } public function setType() { $this->vehicle->type = Vehicle::TRAILER; } public function getVehicle() { return $this->vehicle; } }
As you see above we just created some implementations of the Builder interface passing the original concrete class in every constructor, then we implemented the helper functions such as setModel, and setType which in turn will provide a full qualified object, finally we called getVehicle to return the Vehicle object like this:
public function getVehicle() { return $this->vehicle; }
Now the final piece is the director class, the main responsibility of the director is to get a builder interface and call the builder methods then retrieve the object.
class VehicleDirector { public function build(VehicleBuilderInterface $builder) { $builder->setModel(); $builder->setEnginesCount(); $builder->setType(); return $builder->getVehicle(); } }
Now to use the builder:
$kiaCar = (new VehicleDirector())->build(new KiaCarBuilder(new Vehicle())); $bmwBus = (new VehicleDirector())->build(new BmwBusBuilder(new Vehicle())); $shevroletTrailer = (new VehicleDirector())->build(new ShevroletTrailerBuilder(new Vehicle()));
If you output the any of these instances for example the $kiaCar you will get an instance of Vehicle with attributes prepared for the kia car.
echo "<pre>"; var_dump($kiaCar); echo "\n"; echo "Vechile Model: " . $kiaCar->model . "\n"; echo "Vechile Engines: " . $kiaCar->enginesCount . "\n"; echo "Vechile Type: " . $kiaCar->type . "\n"; echo "<hr/>"; var_dump($bmwBus); echo "\n"; echo "Vechile Model: " . $bmwBus->model . "\n"; echo "Vechile Engines: " . $bmwBus->enginesCount . "\n"; echo "Vechile Type: " . $bmwBus->type . "\n"; echo "<hr/>"; var_dump($shevroletTrailer); echo "\n"; echo "Vechile Model: " . $shevroletTrailer->model . "\n"; echo "Vechile Engines: " . $shevroletTrailer->enginesCount . "\n"; echo "Vechile Type: " . $shevroletTrailer->type . "\n"; echo "<pre>";Â
Someone might ask why we use the builder pattern instead we can get a similar behavior if you provide to our constructor the required parameters and get the same result, and the answer is that as we mentioned in the beginning of the article that there are some cases that we need to get a full qualified object in just one line of code without going with all the required steps of initialization, setting attributes and calling methods.Â