Abstract factory, in italiano fabbrica astratta, è uno dei design pattern creazionali fondamentali della programmazione orientata agli oggetti. Fu definito originariamente dalla cosiddetta Gang of Four.
L'Abstract Factory fornisce un'interfaccia per creare famiglie di oggetti connessi o dipendenti tra loro, in modo che non ci sia necessità da parte dei client di specificare i nomi delle classi concrete all'interno del proprio codice.
In questo modo si permette che un sistema sia indipendente dall'implementazione degli oggetti concreti e che il client, attraverso l'interfaccia, utilizzi diverse famiglie di prodotti.
Questo pattern è utile quando
AbstractFactory
Dichiara l'interfaccia per le operazioni che creano oggetti.
ConcreteFactory
Implementa le operazioni per creare oggetti concreti.
AbstractProduct
Dichiara l'interfaccia per un tipo di oggetto prodotto.
ConcreteProduct
Implementa l'interfaccia AbstractProduct
e definisce l'oggetto prodotto che deve essere creato dalla factory concreta corrispondente.
Client
Utilizza solo le interfacce dichiarate da AbstractFactory
e AbstractProduct
.
ConcreteFactory
a run-time. Questa istanza gestisce la creazione di una sola famiglia di oggetti con un'implementazione specifica. Per creare oggetti di un'altra famiglia bisogna istanziare un'altra factory.AbstractFactory
delega la creazione di oggetti prodotto alle sue sottoclassi ConcreteFactory
.AbstractProduct
, in modo che anche il codice successivo all'istanziazione sia indipendente dal nome della classe che effettivamente implementa il prodotto concreto.AbstractFactory
permette di rispettare questo vincolo.AbstractFactory
definisce tutte le varie tipologie di prodotti che è possibile istanziare, aggiungere una famiglia significa modificare l'interfaccia della factory. La modifica si ripercuote a cascata nelle factory concrete e in tutte le sottoclassi, rendendo laboriosa l'operazione.ConcreteFactory
come Singleton ci si assicura che esista una sola istanza della classe a run-time, accessibile pubblicamente.AbstractFactory
definisce solo l'interfaccia, la creazione dei prodotti è responsabilità delle classi ConcreteFactory
. Si può utilizzare un Factory method per ogni prodotto, metodi che saranno sovrascritti dalle factory concrete. Lo svantaggio di questa tecnica è l'obbligo di dover implementare una factory diversa anche se i tipi di prodotto sono molto simili tra loro. Per risolvere questo problema si può usare il Prototype pattern./*
* GUIFactory example
*/
public abstract class GUIFactory {
public static GUIFactory getFactory() {
int sys = readFromConfigFile("OS_TYPE");
if (sys == 0) {
return new WinFactory();
} else {
return new OSXFactory();
}
}
public abstract Button createButton();
}
class WinFactory extends GUIFactory {
public Button createButton() {
return new WinButton();
}
}
class OSXFactory extends GUIFactory {
public Button createButton() {
return new OSXButton();
}
}
public abstract class Button {
public abstract void paint();
}
class WinButton extends Button {
public void paint() {
System.out.println("Sono un WinButton!");
}
}
class OSXButton extends Button {
public void paint() {
System.out.println("Sono un OSXButton!");
}
}
public class Application {
public static void main(String[] args) {
GUIFactory factory = GUIFactory.getFactory();
Button button = factory.createButton();
button.paint();
}
// L'output sarà:
// "Sono un WinButton!"
// oppure:
// "Sono un OSXButton!"
}