Ce este
Șablonul Abstract Factory (fabrica abstractă) creează familii întregi de obiecte înrudite, care merg împreună. Acolo unde o metodă-fabrică produce un singur produs, o fabrică abstractă produce un set potrivit — și garantează că piesele nu se amestecă niciodată.
Cazul clasic este tematizarea: o temă deschisă trebuie să producă butoane deschise și etichete deschise, niciodată un amestec.
Exemplu: o fabrică de teme
renderScreen primește orice UIFactory și construiește din ea un ecran coerent. Schimbarea întregului aspect ține de un singur argument — iar amestecarea temelor este imposibilă prin construcție.
O fabrică, o familie coerentă
Tema deschisă produce numai componente deschise, tema întunecată numai componente întunecate. renderScreen nu se schimbă niciodată.
Ieșire: script PHP
<?php
interface Button {
public function render(): string;
}
interface Label {
public function render(): string;
}
// Fabrica abstractă creează o întreagă familie de componente potrivite.
interface UIFactory {
public function newButton(): Button;
public function newLabel(): Label;
}
class LightButton implements Button {
public function render(): string {
return "[ OK ] buton deschis";
}
}
class LightLabel implements Label {
public function render(): string {
return "hello etichetă deschisă";
}
}
class DarkButton implements Button {
public function render(): string {
return "[ OK ] buton întunecat";
}
}
class DarkLabel implements Label {
public function render(): string {
return "hello etichetă întunecată";
}
}
class LightTheme implements UIFactory {
public function newButton(): Button {
return new LightButton();
}
public function newLabel(): Label {
return new LightLabel();
}
}
class DarkTheme implements UIFactory {
public function newButton(): Button {
return new DarkButton();
}
public function newLabel(): Label {
return new DarkLabel();
}
}
function renderScreen(UIFactory $f): void {
echo $f->newLabel()->render(), "\n";
echo $f->newButton()->render(), "\n";
}
renderScreen(new LightTheme());
renderScreen(new DarkTheme());
Când să îl folosești
Folosește-l atunci când mai multe obiecte trebuie să rămână coerente între ele — teme, seturi de componente specifice unei platforme, perechi potrivite de formate de import/export.
Renunță la el atunci când produsele nu trebuie să se potrivească între ele. Obiectele independente merită constructori independenți, nu o fabrică de familii.
Avantaje și dezavantaje
Avantaje: coerența familiei este garantată; familiile întregi se schimbă printr-o singură valoare; codul apelant depinde numai de interfețe.
Dezavantaje: foarte multe interfețe și clase pentru o sarcină mică; adăugarea unui produs nou în familie înseamnă modificarea fiecărei fabrici.