L'uso dell'adattatore fa sorgere un nuovo problema nella progettazione: chi crea gli adattatori? E come stabilire quale classe di adattatore creare?
Se questi vengono creati da un oggetto di dominio, le responsabilità dell'oggetto di dominio vanno oltre la logica applicativa pura (come il calcolo del totale di una vendita) ed entrano in gioco altri interessi relativi alla connessione con i componenti software esterni.
Questo punto sottolinea un altor principio fondamentale della progettazione: progettare per mantenere una separazione degli interessi. Ciò significa dividere in moduli o separare interessi distinti in aree diverse, in modo che ciascuno abbia uno scopo coeso. Sostanzialmente è un applicazione di High Cohesion. Per esempio, lo strato del dominio di oggetti software enfatizza responsabilità di logica applicativa relativamente pura, mentre un gruppo diverso di oggetti è responsabile dell'interesse della connessione ai sistemi esterni.
Pertanto la scelta di un oggetto di dominio per creare adattatori non sostiene l'obiettivo della separazione degli interessi e riduce la sua coesione. Un'alternativa è l'applicazione di una Factory (fabbrica) di oggetti.
Nome | Factory |
---|---|
Problema | Chi deve essere responsabile della creazione di oggetti che non c'entrano con il modello di dominio, come gli adapter, con il fine di mantenere una coesione alta del sistema e separare gli interessi tra i vari oggetti? |
Soluzione | Creare un oggetto Pure Fabrication che si comporti come una Factory di oggetti e che gestisce, quindi, la loro creazione. |
Factory non è esattamente un pattern di GoF, ma una semplificazione del pattern GoF Abstract Factory, spesso descritto come una sua variante (anche se ciò non è completamente vero).
Gli oggetti factory consentono diversi vantaggi:
Una soluzione basata su factory è mostrata di seguito
I metodi factory restituiscono oggetti cui il tipo è una interfaccia, anziché una classe, in tal modo la factory può restituire una qualsiasi implementazione dell'interfaccia.
Nel frammento di codice sopra viene utilizzata la java reflection per trovare la classe giusta (leggendola da una proprietà esterna). Non andremo nel dettaglio su questa procedura, tuttavia si può considerare che si possono creare dei file di sistema (POS.properies) da cui si preleva, per esempio nel caso esaminato sopra, il nome della classe da creare. L'amministratore dell'applicazione può modificare tale file nel caso in cui dovessero essere introdotti nuovi adattatori che svolgono funzionalità diverse, modificando solo le properties è possibile creare oggetti diversi, senza modificare la factory.
Abstract Factory è un pattern più generico di Factory.
Factory consente di creare oggetti di diverse famiglie, restituendo una interfaccia per quella famiglia, quindi consentendo di poter creare, di quella famiglia, oggetti più specifici.
Abstract Factory invece consente di avere a disposizione più factory di diverse famiglie di oggetti.
Per comprendere meglio:
Per esempio: consideriamo un kit pe rinterfacce che supporta diversi look standard per l'interfaccia (grafica). Per esempio un tipo flat e uno 3D. Differenti look hanno comportamenti diversi e appaiono diversamente all'utente. Per esempio le finestre e i bottoni saranno diversi nel tipo flat o nel tipo 3D. Per avere entrambe le interfacce esse non dovrebbero essere codificate staticamente. Istanziare staticamente le classi rende difficile la modifica in un secondo momento dello stile.
Abbiamo due tipologie di stile:
Entrambe le classi hanno gli stessi elementi, ma stili diversi.
Allora ciò che dovremmo fare è avere un fabbrica che crea bottoni, finestre e colori per il tipo flat e una che faccia la stessa cosa per lo stile 3D.
Questo potrebbe bastare: creo la mia classe che usa i componenti grafici, ma ho ancora un vincolo, devo usare una delle due fabbriche, quella flat o quella 3D (questo è il pattern factory), quello che si vuole è avere una fabbrica di fabbriche che ci consenta di cambiare dinamicamente la fabbrica di cui vogliamo fare uso.
Il client potrebbe essere la classe che usa vari tipologie di stile.
L'abstract factory consente di creare delle fabbriche concrete che generano oggetti di diverso tipo con quello stile.
La factory 1 per esempio:
Il Client ha degli oggetti non concreti degli componenti grafici che vuole usare, ma non sa ancora quale stile li implementerà.
Il Client ha i componenti (le interfacce), ma in base alla factory istanzia gli oggetti con lo stile che preferisce.