Ce este
Șablonul Builder construiește un obiect complex pas cu pas. În locul unui singur constructor cu o listă lungă și confuză de argumente, builderul oferă pași mici, cu nume — și un build() final care returnează obiectul finalizat.
În PHP pașii returnează $this, așa că apelurile se înlănțuie într-o propoziție ușor de citit.
Exemplu: construirea unei pizza
Compară (new PizzaBuilder("large"))->cheese()->topping("mushrooms") cu un constructor de forma new Pizza("large", true, [...]) — builderul spune ce înseamnă fiecare valoare, iar părțile opționale sunt pur și simplu omise.
Pași care se înlănțuie
Fiecare pas are un nume și este opțional: pizza small îi omite pe toți. Fără supa de argumente true, null, false — iar ingredientele se afișează ca o listă simplă separată prin virgulă, respectiv none când nu există niciunul.
Ieșire: script PHP
<?php
class Pizza {
public function __construct(
public string $size,
public bool $cheese,
public array $toppings,
) {}
}
class PizzaBuilder {
private bool $cheese = false;
private array $toppings = [];
public function __construct(private string $size) {}
public function cheese(): self {
$this->cheese = true;
return $this;
}
public function topping(string $t): self {
$this->toppings[] = $t;
return $this;
}
public function build(): Pizza {
return new Pizza($this->size, $this->cheese, $this->toppings);
}
}
function describe(Pizza $p): void {
$toppings = $p->toppings === [] ? "none" : implode(", ", $p->toppings);
printf("pizza %s, brânză: %s, ingrediente: %s\n",
$p->size, var_export($p->cheese, true), $toppings);
}
$big = (new PizzaBuilder("large"))
->cheese()
->topping("mushrooms")
->topping("olives")
->build();
$small = (new PizzaBuilder("small"))->build();
describe($big);
describe($small);
Când să-l folosești
Folosește-l când un obiect are multe părți opționale sau când construcția are pași reali care merită nume. Cererile, interogările și configurațiile sunt teritoriul clasic al builderului.
Renunță la el pentru obiecte simple — argumentele numite din PHP, new Pizza(size: "large"), fac deja ca un constructor obișnuit să se citească bine în cazurile ușoare.
Avantaje și dezavantaje
Avantaje: construcție ușor de citit; părți opționale fără liste uriașe de argumente; obiectul poate fi validat o singură dată, în build().
Dezavantaje: încă o clasă de scris și de întreținut; este exagerat acolo unde un constructor obișnuit se citește deja bine.