L’Abstract Factory, ovvero fabbrica astratta, è uno dei fondamentali design pattern. Questo pattern si occupa di fornire al programmatore un interfaccia per la creazione di oggetti connessi tra loro, senza che lo stesso debba interessarsi della logica implementativa riguardante la creazione degli stessi.
Lo scopo principale di questo pattern quindi, è quello di realizzare una certa indipendenza dei client dagli oggetti che utilizzano, nella misura in cui possono creare e utilizzare diverse famiglie di oggetti senza conoscerne i dettagli.
Il pattern Abstract Factory risulta molto utile nei seguenti casi
si vuole mantenere una stretta indipendenza dei client dalle modalità con le quali gli oggetti vengono gestiti
è necessario poter configurare il sistema scegliendo tra diverse famiglie di oggetti
occorre fornire una libreria di classi nascondendone però l’implementazione
si vuole vincolare determinate famiglie di oggetti a utilizzare oggetti della medesima famiglia
Queste sono le principali conseguenze dell’applicazione del pattern:
Isolamento delle classi concrete: la factory viene utilizzata dai client esclusivamente tramite la sua interfaccia, realizzando di fatto la massima indipendenza dalle implementazioni dei prodotti. I client per poter utilizzare i prodotti che la fabbrica restituisce, avranno a disposizione le interfacce AbstractProduct.
Facilità di modifica della famiglia dei prodotti: visto che la ConcreteFactory viene istanziata una sola volta, basta predisporre un meccanismo di modifica a run-time della ConcreteFactory e saremo in grado di lavorare con un altra famiglia di prodotti.
Corenza nell’utilizzo dei prodotti: consente a dei prodotti appositamente progettati per lavorare assieme, di rispettare questo vincolo.
Come si può osservare dallo schema sottostante, l’AbstractFactory dichiara l’interfaccia per le operazioni che creano i prodotti astratti e le ConcreteFactory implementano le operazioni necessarie alla costruzione degli oggetti.
Da notare come nello schema, sono presenti anche le classi AbstractProduct e le classi ConcreteProduct. Le prime rappresentano l’interfacce generiche e astratte del prodotto, mentre le seconde saranno le classi delegate all’implementazione dei prodotti e alla loro costruzione.
In generale, per applicare questo pattern correttamente, occorre creare una sola istanza di ConcreteFactory (mediante il pattern Singleton), la quale si occuperà a sua volta di gestire il processo di creazione di una sola famiglia di oggetti, sebbene seguendo delle implementazioni specifiche.
La creazione dei prodotti viene delegata alla ConcreteFactory tramite un metodo apposito denominato Factory Method il quale, richiamato dall’interfaccia, sarà però necessariamente implementato nelle ConcreteFactory.
Se volessimo, perciò, creare oggetti di un’altra famiglia bisognerebbe creare ed istanziare un’altra factory.