Design patterns: Abstract Factory
L’Abstract Factory Pattern è un design pattern creazionale che fornisce un’interfaccia per creare famiglie di oggetti correlati o dipendenti senza specificarne le classi concrete. Questo pattern è utile quando si desidera garantire che un’insieme di oggetti appartenga a una certa famiglia e venga utilizzato in modo coerente.g
Caratteristiche del Abstract Factory pattern
- Creazione di famiglie di Oggetti: Permette di creare gruppi di oggetti che appartengono a una certa famiglia o contesto, garantendo che siano compatibili tra loro.
- Interfaccia astratta: Fornisce un’interfaccia astratta che definisce i metodi per creare gli oggetti. Le classi concrete implementano questa interfaccia per fornire la logica di creazione specifica.
- Indipendenza dalle Classi concrete: L’utente non è a conoscenza delle classi concrete che vengono create. Può utilizzare l’interfaccia dell’abstract factory senza preoccuparsi di come sono implementate le classi concrete.
- Facilita l’estensione: Aggiungere nuovi prodotti o famiglie di prodotti diventa più facile. È sufficiente creare una nuova classe che implementa l’interfaccia astratta senza modificare il codice esistente.
- Coerenza: Assicura che gli oggetti creati siano coerenti tra loro. Ad esempio, se si crea un’interfaccia utente, si possono generare elementi come bottoni e finestre che appartengono allo stesso tema visivo.
- Supporto per la variabilità: Consente di cambiare la famiglia di oggetti creati senza modificare il codice client. Puoi passare a una diversa implementazione dell’abstract factory e ottenere oggetti completamente diversi.
Esempio in PHP:
Immaginiamo di avere due tipi di auto, ognuna delle quali ha due componenti: Sedili e Motore. Possiamo creare due famiglie di auto: Auto di Lusso e Auto Sportiva.
// Interfaccia per i sedili
interface Seats {
public function createSeats();
}
// Interfaccia per i motori
interface Engine {
public function createEngine();
}
// Sedili per auto di lusso
class LuxurySeats implements Seats {
public function createSeats() {
return "Sedili di lusso";
}
}
// Sedili per auto sportive
class SportSeats implements Seats {
public function createSeats() {
return "Sedili sportivi";
}
}
// Motore per auto di lusso
class LuxuryEngine implements Engine {
public function createEngine() {
return "Motore di lusso";
}
}
// Motore per auto sportive
class SportEngine implements Engine {
public function createEngine() {
return "Motore sportivo";
}
}
// Abstract Factory
interface CarFactory {
public function createSeats(): Seats;
public function createEngine(): Engine;
}
// Factory per auto di lusso
class LuxuryCarFactory implements CarFactory {
public function createSeats(): Seats {
return new LuxurySeats();
}
public function createEngine(): Engine {
return new LuxuryEngine();
}
}
// Factory per auto sportive
class SportCarFactory implements CarFactory {
public function createSeats(): Seats {
return new SportSeats();
}
public function createEngine(): Engine {
return new SportEngine();
}
}
// Utilizzo
function buildCar(CarFactory $factory) {
$seats = $factory->createSeats();
$engine = $factory->createEngine();
echo $seats->createSeats() . " con " . $engine->createEngine() . "\n";
}
$factoryLuxury = new LuxuryCarFactory();
$factorySport = new SportCarFactory();
buildCar($factoryLuxury); // Sedili di lusso con Motore di lusso
buildCar($factorySport); // Sedili sportivi con Motore sportivo
Caso d’uso frequente
Un esempio classico è un’applicazione che gestisce interfacce utente per diversi sistemi operativi (Windows, macOS, Linux). L’abstract factory può fornire metodi per creare componenti come finestre, pulsanti e menu, garantendo che tutti gli oggetti siano progettati per funzionare insieme e rispettare lo stile del sistema operativo specificato.