1.2. Builder

1.2.1. Amaç

Yapıcı, karmaşık bir nesnenin parçalarını oluşturan bir arayüzdür.

Bazen yapıcı, oluşturduğu şey hakkında daha iyi bir bilgiye sahipse, bir arayüz (interface) yerine varsayılan yöntemlere (method) sahip soyut bir sınıf (class) olabilir (diğer bir deyişle bir adaptör (adapter)).

Eğer nesneler için girift bir kalıtım ağacınız (inheritance tree) varsa, yapıcılar için de girift bir kalıtım ağacınızın olması mantıklı olacaktır.

Not: Yapıcılar çoğu zaman akıcı bir arayüze sahiptir, örneğin PHPUnit’in yapay (mock) yapıcısına bakabilirsiniz.

1.2.2. Örnekler

  • PHPUnit: Mock Builder

1.2.3. UML Diyagramı

Alt Builder UML Diyagramı

1.2.4. Kod

Bu kodu Github üzerinde de bulabilirsiniz.

Director.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Creational\Builder;
 6
 7use DesignPatterns\Creational\Builder\Parts\Vehicle;
 8
 9/**
10 * Director is part of the builder pattern. It knows the interface of the builder
11 * and builds a complex object with the help of the builder
12 *
13 * You can also inject many builders instead of one to build more complex objects
14 */
15class Director
16{
17    public function build(Builder $builder): Vehicle
18    {
19        $builder->createVehicle();
20        $builder->addDoors();
21        $builder->addEngine();
22        $builder->addWheel();
23
24        return $builder->getVehicle();
25    }
26}

Builder.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Creational\Builder;
 6
 7use DesignPatterns\Creational\Builder\Parts\Vehicle;
 8
 9interface Builder
10{
11    public function createVehicle(): void;
12
13    public function addWheel(): void;
14
15    public function addEngine(): void;
16
17    public function addDoors(): void;
18
19    public function getVehicle(): Vehicle;
20}

TruckBuilder.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Creational\Builder;
 6
 7use DesignPatterns\Creational\Builder\Parts\Door;
 8use DesignPatterns\Creational\Builder\Parts\Engine;
 9use DesignPatterns\Creational\Builder\Parts\Wheel;
10use DesignPatterns\Creational\Builder\Parts\Truck;
11use DesignPatterns\Creational\Builder\Parts\Vehicle;
12
13class TruckBuilder implements Builder
14{
15    private Truck $truck;
16
17    public function addDoors(): void
18    {
19        $this->truck->setPart('rightDoor', new Door());
20        $this->truck->setPart('leftDoor', new Door());
21    }
22
23    public function addEngine(): void
24    {
25        $this->truck->setPart('truckEngine', new Engine());
26    }
27
28    public function addWheel(): void
29    {
30        $this->truck->setPart('wheel1', new Wheel());
31        $this->truck->setPart('wheel2', new Wheel());
32        $this->truck->setPart('wheel3', new Wheel());
33        $this->truck->setPart('wheel4', new Wheel());
34        $this->truck->setPart('wheel5', new Wheel());
35        $this->truck->setPart('wheel6', new Wheel());
36    }
37
38    public function createVehicle(): void
39    {
40        $this->truck = new Truck();
41    }
42
43    public function getVehicle(): Vehicle
44    {
45        return $this->truck;
46    }
47}

CarBuilder.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Creational\Builder;
 6
 7use DesignPatterns\Creational\Builder\Parts\Door;
 8use DesignPatterns\Creational\Builder\Parts\Engine;
 9use DesignPatterns\Creational\Builder\Parts\Wheel;
10use DesignPatterns\Creational\Builder\Parts\Car;
11use DesignPatterns\Creational\Builder\Parts\Vehicle;
12
13class CarBuilder implements Builder
14{
15    private Car $car;
16
17    public function addDoors(): void
18    {
19        $this->car->setPart('rightDoor', new Door());
20        $this->car->setPart('leftDoor', new Door());
21        $this->car->setPart('trunkLid', new Door());
22    }
23
24    public function addEngine(): void
25    {
26        $this->car->setPart('engine', new Engine());
27    }
28
29    public function addWheel(): void
30    {
31        $this->car->setPart('wheelLF', new Wheel());
32        $this->car->setPart('wheelRF', new Wheel());
33        $this->car->setPart('wheelLR', new Wheel());
34        $this->car->setPart('wheelRR', new Wheel());
35    }
36
37    public function createVehicle(): void
38    {
39        $this->car = new Car();
40    }
41
42    public function getVehicle(): Vehicle
43    {
44        return $this->car;
45    }
46}

Parts/Vehicle.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Creational\Builder\Parts;
 6
 7abstract class Vehicle
 8{
 9    final public function setPart(string $key, object $value)
10    {
11    }
12}

Parts/Truck.php

1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Creational\Builder\Parts;
6
7class Truck extends Vehicle
8{
9}

Parts/Car.php

1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Creational\Builder\Parts;
6
7class Car extends Vehicle
8{
9}

Parts/Engine.php

1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Creational\Builder\Parts;
6
7class Engine
8{
9}

Parts/Wheel.php

1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Creational\Builder\Parts;
6
7class Wheel
8{
9}

Parts/Door.php

1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Creational\Builder\Parts;
6
7class Door
8{
9}

1.2.5. Test

Tests/DirectorTest.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Creational\Builder\Tests;
 6
 7use DesignPatterns\Creational\Builder\Parts\Car;
 8use DesignPatterns\Creational\Builder\Parts\Truck;
 9use DesignPatterns\Creational\Builder\TruckBuilder;
10use DesignPatterns\Creational\Builder\CarBuilder;
11use DesignPatterns\Creational\Builder\Director;
12use PHPUnit\Framework\TestCase;
13
14class DirectorTest extends TestCase
15{
16    public function testCanBuildTruck()
17    {
18        $truckBuilder = new TruckBuilder();
19        $newVehicle = (new Director())->build($truckBuilder);
20
21        $this->assertInstanceOf(Truck::class, $newVehicle);
22    }
23
24    public function testCanBuildCar()
25    {
26        $carBuilder = new CarBuilder();
27        $newVehicle = (new Director())->build($carBuilder);
28
29        $this->assertInstanceOf(Car::class, $newVehicle);
30    }
31}