PHP-设计模式-建造者模式(Builder)

目的

创建一个复杂对象的一部分接口。

用处

如果一个类中有很多属性,为了避免构造函数的参数列表过长,影响代码的可读性和医用性,可以通过构造函数配合set()方法来解决。但是,如果存在下面情况的任意一种,我们就要考虑使用建造者模式了。

  • 把类的必填属性放到构造函数中,强制创建对象的时候就设置。如果必填的属性有很多,把这些必填属性都放到构造函数中设置,那构造函数就又会出现参数列表很长的问题。如果我们把必填属性通过set()方法设置,那校验这些必填属性是否已经填写的逻辑就无处安放了。
  • 如果类的属性之间有一定的依赖关系或者约束条件,我们继续使用构造函数配合set()方法的设计思路,那些依赖关系或约束条件的校验逻辑就无处安放了。
  • 如果希望创建不可变对象,也就是说,对象在创建好之后,就不能再修改内部的属性值,要实现这个功能,我们就不能在类中暴露set()方法。构造函数配合set()方法来设置属性值的方式就不适用了。

代码

<?php


namespace DesignPatterns\Creational\Builder\Parts;


class Car extends Vehicle
{

}
<?php


namespace DesignPatterns\Creational\Builder\Parts;


class Door
{

}
<?php


namespace DesignPatterns\Creational\Builder\Parts;


class Engine
{

}
<?php


namespace DesignPatterns\Creational\Builder\Parts;


class Truck extends Vehicle
{

}
<?php


namespace DesignPatterns\Creational\Builder\Parts;


abstract class Vehicle
{
    protected $data = [];

    public function setPart($key, $value)
    {
        $this->data[$key] = $value;
    }
}
<?php


namespace DesignPatterns\Creational\Builder\Parts;


class Wheel
{

}
<?php


namespace DesignPatterns\Creational\Builder;


interface BuilderInterface
{
    public function createVehicle();
    public function addDoors();
    public function addEngine();
    public function addWheel();
    public function getVehicle();
}
<?php


namespace DesignPatterns\Creational\Builder;


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

class CarBuilder implements BuilderInterface
{
    protected $car;

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

    public function addDoors()
    {
        $this->car->setPart('rightDoors', new Door());
        $this->car->setPart('leftDoors', 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 getVehicle()
    {
        return $this->car;
    }
}
<?php


namespace DesignPatterns\Creational\Builder;


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

class TruckBuilder implements BuilderInterface
{
    private $truck;

    public function createVehicle()
    {
        $this->truck = new Truck();
    }

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

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

    public function addWheel()
    {
        $this->truck->setPart('rightWheel1', new Wheel());
        $this->truck->setPart('rightWheel2', new Wheel());
        $this->truck->setPart('rightWheel3', new Wheel());
        $this->truck->setPart('leftWheel1', new Wheel());
        $this->truck->setPart('leftWheel2', new Wheel());
        $this->truck->setPart('leftWheel3', new Wheel());
    }

    public function getVehicle()
    {
        return $this->truck;
    }
}
<?php


namespace DesignPatterns\Creational\Builder;


class Director
{
    public function build(BuilderInterface $builder)
    {
        $builder->createVehicle();
        $builder->addDoors();
        $builder->addEngine();
        $builder->addWheel();

        return $builder->getVehicle();
    }
}
<?php


namespace Tests;


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

class BuilderTest extends TestCase
{
    public function testCanBuilderCar()
    {
        $builder = new CarBuilder();
        $director = new Director();
        $vehicle = $director->build($builder);
        $this->assertInstanceOf(Car::class, $vehicle);
    }

    public function testCanBuilderTruck()
    {
        $builder = new TruckBuilder();
        $director = new Director();
        $vehicle = $director->build($builder);
        $this->assertInstanceOf(Truck::class, $vehicle);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值