I design pattern creazionali astraggono il processo di istanziazione.
Consentono di rendere il sistema indipendente da come gli oggetti sono creati, rappresentati e delle relazioni di composizione tra essi.
Se basati su classi, utilizzano l’ereditarietà per modificare la classe istanziata.
Se basati su oggetti, delegano l’istanziazione ad altri oggetti.
Incapsulano la conoscenza relativa alle classi concrete utilizzate dal sistema.
Nascondono come le istanze delle classi sono create e assemblate.
Alcuni creational patterns catalogati:
Esempi di creational patterns illustrati in dettaglio nel seguito:
Fornire un’ interfaccia per creare famiglie di oggetti dipendenti o correlati senza specificare la loro classe concreta.
Analogia: una macchina per fare la pasta.
Si consideri un’applicazione la cui interfaccia grafica fornisce all’utilizzatore aspetti diversi a cui sono associati comportamenti diversi dei widget (scroll bar, finestre, bottoni).
Affinchè l’applicazione possa fornire diversi aspetti e comportamenti (look-and-feel) occorre che i widget non siano codificati per il particolare aspetto: istanziare delle classi specifiche dei widget per ogni aspetto complicherebbe il successivo cambio di aspetto.
WidgetFactory è una classe astrattale cui sottoclassi implementano le operazioni per creare il widget appropriato per il particolare aspetto.
I client creano i widget utilizzando solo l’interfaccia WidgetFactory e senza avere alcuna conoscenza delle classi che implementano i widget per un particolare aspetto.
Usiamo un Abstract Factory quando:
AbstractFactory -Dichiara un’interfaccia per operazioni che creano prodotti astratti.
ConcreteFactory - Implementa le operazioni per creare oggetti prodotto concreti: solitamente istanziata come un singleton.
AbstractProduct - Dichiara un’interfaccia per un tipo di oggetto prodotto.
ConcreteProduct - Definisce un oggetto prodotto che deve essere creato con la corrispondente ConcreteFactory.
Vantaggi
Svantaggi
Solitamente un’applicazione richiede un’unica istanza di ConcreteFactory per cui viene solitamente implementata come un Singleton.
AbstractFactory è solo un’interfaccia per la creazione dei prodotti che devono poi essere creati da ConcreteFactory; ciò può essere realizzato attraverso un factory method.
È possibile utilizzare dei metodi parametrizzati per specificare il particolare oggetto da creare, come per i factory method.
Definisce un’interfaccia per creare un oggetto, ma lascia decidere alle sottoclassi quale classe istanziare.
Lascia che una classe deleghi l’istanziazione alle sottoclassi.
Si consideri un framework per applicazioni che lavorano su documenti di diverso tipo.
Abbiamo due astrazioni: Application e Document.
La classe Application è responsabile della gestione di Document.
Ma Application sa quando creare un documento, ma non il tipo di Document da creare.
A sua volta, il framework deve istanziare classi, ma vede solo classi astratte che non può istanziare.
In Application definiamo un metodo CreateDocument();
MyApplication fa in modo che createDocument() crei un prodotto (Document) del tipo corretto.
Il pattern Factory Method è utilizzato quando:
Product (Document)
ConcreteProduct (MyDocument)
Creator (Application)
ConcreteCreator (MyApplication)
Vantaggi
La creazione di oggetti in una classe con un factory method è più flessibile della creazione diretta di un oggetto, per cui le sottoclassi sono agevolate nella creazione di versioni estese degli oggetti;
Connette gerarchie di classi parallele: classi che delegano responsabilità ad altre classi.
La classe Figure fornisce il factory method CreateManipulator che lascia che siano I client a creare il Manipulator corrispondente alla particolare Figure.
Svantaggi potenziali
I clients devono derivare la classe Creator solo per creare un particolare oggetto ConcreteProduct.
Creator è una classe astratta che dichiara un Factory Method astratto e ConcreteCreator lo implementa.
Creator definisce una implementazione di default per Factory Method.
Factory Methods parametrizzati:
Mostra codiceAssicura che una classe abbia una sola istanza e fornisce un punto globale di accesso ad essa.
In alcuni casi è importante che una classe abbia esattamente un’istanza.
Una variabile esterna fa sì che l’oggetto sia accessibile, ma non impedisce che siano istanziati più oggetti.
La classe stessa è responsabile di avere traccia della sua unica istanza e fornire un modo per accedere a tale istanza.
Il Singleton va usato quando:
Singleton
Istance()
che consente ai clients di accedere la sua unica istanza;Instance()
è un metodo di classe (i.e. static);Accesso controllato all’unica istanza.
Un sostituto elegante per variabili esterne (consente di evitare l’”inquinamento” del name space con numerose variabili esterne).
Il Singleton può essere esteso per consentire un numero variaible di istanze.
Una tecnica per garantire che vi sia una sola istanza della classe consiste nel nascondere l’operazione di creazione in una operazione di classe (funzione static) e rendendo il costruttore protected.
Mostra codiceNel caso di sottoclassi, occorre fare in modo che l’unica istanza della classe derivata sia accessibile in modo che i client possano utilizzarla.
Una possibile soluzione nel determinare il Singleton che si intende utilizzare nell’operazione Istance()
:
Singleton* Singleton::Instance() {
if(condition)
_instance= new particularInstance;
}
2. La modellazione a oggetti e il linguaggio UML (richiami)
3. Generalità su Java e la programmazione ad oggetti
6. Regole di traduzione da UML a Java/C++
7. Programmazione multi-thread
8. Sincronizzazione tra thread
9. Programmazione client-server con socket TCP/IP (Java networkin...
10. Programmazione di applicazioni client-server: il Pattern Proxy...
12. Design Patterns
13. Pattern architetturali - Esempi
14. Design pattern creazionali. Esempi
15. Design pattern strutturali. Esempi
16. Introduzione alle tecnologie middleware
17. Modelli di middleware: RPC, MOM, TP, TS