Ответ
Паттерн Builder отделяет конструирование сложного объекта от его представления, позволяя создавать разные представления объекта, используя один и тот же процесс построения.
Классическая реализация (из GoF):
// 1. Продукт, который мы строим
class Car
{
private string $engine = '';
private int $seats = 0;
private bool $hasGPS = false;
private bool $hasTripComputer = false;
public function setEngine(string $engine): void { $this->engine = $engine; }
public function setSeats(int $seats): void { $this->seats = $seats; }
public function setGPS(bool $hasGPS): void { $this->hasGPS = $hasGPS; }
public function setTripComputer(bool $hasTripComputer): void { $this->hasTripComputer = $hasTripComputer; }
public function getDescription(): string
{
return sprintf(
"Car with %s engine, %d seats%s%s.",
$this->engine,
$this->seats,
$this->hasGPS ? ', GPS' : '',
$this->hasTripComputer ? ', Trip Computer' : ''
);
}
}
// 2. Интерфейс Строителя
interface CarBuilder
{
public function reset(): void;
public function buildEngine(): void;
public function buildSeats(): void;
public function buildGPS(): void;
public function buildTripComputer(): void;
public function getResult(): Car;
}
// 3. Конкретный строитель для спортивного автомобиля
class SportsCarBuilder implements CarBuilder
{
private Car $car;
public function reset(): void { $this->car = new Car(); }
public function buildEngine(): void { $this->car->setEngine('V8 Turbo'); }
public function buildSeats(): void { $this->car->setSeats(2); }
public function buildGPS(): void { $this->car->setGPS(true); } // В спортивной версии есть GPS
public function buildTripComputer(): void { $this->car->setTripComputer(true); }
public function getResult(): Car { return $this->car; }
}
// 4. Директор, который управляет процессом построения
class Director
{
public function constructSportsCar(CarBuilder $builder): Car
{
$builder->reset();
$builder->buildEngine();
$builder->buildSeats();
$builder->buildGPS();
$builder->buildTripComputer();
return $builder->getResult();
}
}
// 5. Клиентский код
$builder = new SportsCarBuilder();
$director = new Director();
$car = $director->constructSportsCar($builder);
echo $car->getDescription(); // Car with V8 Turbo engine, 2 seats, GPS, Trip Computer.
Почему это полезно:
- Изоляция сложной логики создания. Клиент (
Director) не знает деталей сборки конкретной модели. - Гибкость. Можно легко добавить нового строителя для
SUVBuilderс другим набором опций, используя тот же интерфейс. - Пошаговое конструирование. Методы
build...можно вызывать в разном порядке или пропускать, если это позволяет строитель.