Utilisateur
L'intento del Factory Method è definire un'interfaccia per creare un oggetto, delegando alle sottoclassi la decisione su quale classe istanziare. È conosciuto anche come "Costruttore Virtuale".
Il Factory Method è utile quando una classe (come Application) deve gestire oggetti (come Document) senza conoscere quale sottoclasse di oggetto utilizzare. Le sottoclassi ridefiniscono il metodo CreateDocument per restituire l'istanza corretta.
Il Factory Method è utile quando:
Una classe non sa quale classe di oggetti deve creare.
Le sottoclassi devono specificare gli oggetti da creare.
Si vuole centralizzare la conoscenza della sottoclasse delegata per creare un oggetto specifico.
Partecipanti:
Product: interfaccia degli oggetti creati dal metodo factory.
ConcreteProduct: implementa l'interfaccia Product.
Creator: dichiara il metodo factory che restituisce un Product.
ConcreteCreator: sovrascrive il metodo factory per restituire un'istanza di ConcreteProduct.
Il Factory Method:
Elimina la necessità di legare classi specifiche per l'applicazione nel codice.
Permette di sottoclassare Creator per creare un particolare ConcreteProduct.
Fornisce "ganci" per le sottoclassi per estendere un oggetto.
Supporta il Principio Aperto/Chiuso.
Il Creator può essere una classe astratta senza implementare il Factory Method.
Il Creator può essere concreto e offrire un'implementazione predefinita.
Si può usare un metodo factory parametrizzato per controllare il tipo di prodotto da creare.
Utilizzato comunemente in Abstract Factory e altri software, per creare oggetti dinamicamente senza legarsi a classi specifiche.
Pattern correlati:
Abstract Factory: utilizza Factory Method per creare famiglie di prodotti.
Template Method: per definire il flusso del metodo factory.
Prototype: come alternativa per creare nuovi oggetti.
L'intento dell'Abstract Factory è fornire un'interfaccia per creare famiglie di oggetti correlati o dipendenti senza specificare le loro classi concrete. È conosciuto anche come "Kit".
L'Abstract Factory è utile in un toolkit UI che supporta diversi standard di look-and-feel. Permette di creare widget compatibili con vari stili senza legare il codice client a un look-and-feel specifico.
L'Abstract Factory è utile quando:
Il sistema deve essere indipendente dai dettagli di creazione dei prodotti.
È necessario configurare il sistema con famiglie di prodotti specifiche.
Una famiglia di prodotti correlati deve essere usata insieme.
Si vuole fornire interfacce di classi di prodotti senza esporne le implementazioni.
Partecipanti:
AbstractFactory: dichiara i metodi per creare prodotti astratti.
ConcreteFactory: implementa la creazione dei prodotti concreti.
AbstractProduct: interfaccia per un tipo di prodotto.
ConcreteProduct: definisce un prodotto concreto e implementa AbstractProduct.
Client: utilizza solo le interfacce di AbstractFactory e AbstractProduct.
Una singola istanza di ConcreteFactory è creata a runtime. La ConcreteFactory crea oggetti di prodotto con una specifica implementazione, e l'AbstractFactory delega la creazione dei prodotti alle sue sottoclassi ConcreteFactory.
L'Abstract Factory:
Isola le classi concrete: il client usa solo interfacce astratte.
Facilita la sostituzione delle famiglie di prodotti modificando solo la factory concreta.
Promuove la coerenza, utilizzando oggetti della stessa famiglia.
Difficile estendere l'interfaccia della factory per nuovi tipi di prodotto.
Implementazione:
Creare un'interfaccia AbstractFactory con metodi di creazione per ogni tipo di prodotto.
Implementare classi ConcreteFactory per ogni variante.
A runtime, usare la configurazione o l'ambiente per selezionare la factory appropriata.
Sostituire le chiamate dirette ai costruttori con chiamate alla factory.
L'Abstract Factory è utilizzato comunemente in applicazioni che richiedono la creazione di interfacce utente multipiattaforma o la gestione di famiglie di oggetti correlati.
Pattern correlati:
Factory Method: spesso implementato all'interno dell'Abstract Factory.
Singleton: usato per assicurare una singola istanza della ConcreteFactory.
Prototype: per creare oggetti duplicando un'istanza esistente.
L'intento del Singleton è garantire che una classe abbia una sola istanza e fornire un punto di accesso globale a questa istanza.
Il Singleton è usato quando è necessario avere una singola istanza di una classe accessibile da un punto globale, evitando che altre istanze vengano create accidentalmente tramite una variabile globale.
Utilizza il Singleton quando:
Deve esistere una sola istanza di una classe accessibile da un punto di accesso noto.
La singola istanza deve essere estendibile tramite sottoclassi, e i client devono poterne usare una senza modifiche.
Partecipanti:
Singleton: definisce l'operazione Instance per accedere alla sua unica istanza, spesso come membro statico, ed è responsabile della creazione della propria istanza unica.
I client accedono esclusivamente all'istanza Singleton tramite il metodo Instance, assicurando che vi sia un unico punto di accesso globale.
Il Singleton offre:
Accesso controllato e centralizzato all'unica istanza.
Riduzione dello spazio dei nomi, eliminando variabili globali.
La possibilità di sottoclassare e raffinare il Singleton per rappresentazioni diverse.
Possibilità di implementare un numero variabile di istanze, se necessario, benché sia complicato in linguaggi come C++.
Implementazione:
Aggiungi un campo statico privato per l'istanza.
Dichiarare un metodo di creazione statico pubblico per restituire l'istanza.
Usa l'inizializzazione "pigra" nel metodo di creazione.
Rendi privato il costruttore.
Sostituisci le chiamate dirette al costruttore nel codice client con il metodo di creazione statico.
Il Singleton è ampiamente usato in molte applicazioni che richiedono accesso centralizzato a un'unica risorsa o a un oggetto condiviso tra vari client.
Pattern correlati:
Abstract Factory: può usare il Singleton per fornire un'unica istanza di una factory.
Builder: gestisce la creazione complessa di oggetti, a volte con Singleton.
Prototype: crea nuovi oggetti clonando un'istanza esistente, alternativa al Singleton.
Intento: Separare la costruzione di un oggetto complesso dalla sua rappresentazione, in modo che lo stesso processo di costruzione possa creare rappresentazioni diverse.
Motivazione:
Un lettore di formato RTF deve essere in grado di convertire in vari formati di testo, come ASCII o un widget di testo interattivo.
Dev’essere facile aggiungere nuove conversioni senza modificare il lettore.
In un oggetto complesso, la costruzione di componenti può richiedere un'inizializzazione laboriosa, e un costruttore enorme può rendere difficile la gestione delle combinazioni dei parametri. Il Builder permette di evitare una crescita esponenziale della gerarchia delle sottoclassi o di costruttori con troppi parametri.
Applicabilità: Usa il pattern Builder quando:
L'algoritmo per costruire un oggetto complesso dovrebbe essere indipendente dalle sue parti e da come vengono assemblate.
Il processo di costruzione deve consentire rappresentazioni diverse per l'oggetto costruito.
Struttura e Partecipanti:
Builder (TextConverter): Interfaccia astratta per creare parti di un prodotto.
ConcreteBuilder (ASCIIConverter, …): Implementa l’interfaccia Builder, costruisce e assemblasse parti del prodotto, e fornisce un'interfaccia per recuperare il prodotto.
Director (RTFReader): Gestisce l'ordine delle fasi di costruzione.
Product (ASCIIText, TeXText, TextWidget): Oggetto complesso in costruzione che include le classi delle sue parti costitutive.
Collaborazioni:
Il client crea l'oggetto Director e lo configura con l'oggetto Builder desiderato.
Il Director invoca il Builder per costruire il prodotto, passo dopo passo.
Il Builder gestisce la costruzione e recupera il prodotto.
Il client recupera il prodotto dal Builder.
Conseguenze:
Permette di variare la rappresentazione interna di un prodotto.
Nasconde la struttura e l'assemblaggio del prodotto dal codice client.
Isola il codice di costruzione dal codice aziendale.
Migliora la modularità e il riuso del codice.
Consente di costruire l'oggetto passo dopo passo, dando un controllo dettagliato sul processo di costruzione.
Implementazione:
Creare una classe astratta Builder con operazioni per ciascuna parte da costruire.
Le ConcreteBuilder implementano i metodi di costruzione specifici per ogni parte del prodotto.
Implementare un metodo per recuperare il prodotto finito.
Creare un Director per incapsulare le sequenze di costruzione, se necessario.
Utilizzi Noti: Utilizzato in molte applicazioni che necessitano di costruire oggetti complessi, come nei sistemi di progettazione, nelle auto (construzione di auto e manuali) e nei lettori di formati complessi come RTF.
Pattern Correlati:
Abstract Factory: Permette di creare famiglie di oggetti correlati, spesso utilizzato insieme al Builder.
Composite: Può essere utilizzato in combinazione con Builder per strutturare prodotti complessi come strutture gerarchiche di oggetti.
Creare nuovi oggetti clonando un'istanza di un prototipo piuttosto che costruire un nuovo oggetto da zero, rendendo il processo di creazione flessibile e meno dipendente dalle classi concrete.
Quando è difficile o inefficiente creare nuovi oggetti da zero, clonare prototipi predefiniti è una soluzione comoda.
Consente di evitare una complessa gerarchia di sottoclassi e permette di creare oggetti da una tavolozza predefinita (es. note musicali in un editor di spartiti).
Quando un sistema deve essere indipendente da come i suoi oggetti sono creati, composti e rappresentati.
Quando le classi da istanziare sono specificate a runtime e quando la gerarchia di classi potrebbe essere ampia.
Quando il sistema deve supportare un numero limitato di configurazioni di stato per gli oggetti.
Prototype (Graphic): Interfaccia per clonare se stesso.
ConcretePrototype (Staff, WholeNote, HalfNote): Implementa l'operazione di clonazione.
Client (GraphicTool): Crea un nuovo oggetto chiedendo al prototipo di clonare se stesso.
Il client chiede al prototipo di clonare se stesso, senza sapere quale classe concreta rappresenti l'oggetto, sfruttando l'interfaccia comune di clonazione.
Nasconde le classi concrete al client, permettendo flessibilità nell'uso degli oggetti.
Riduce la necessità di una gerarchia complessa di sottoclassi.
Permette di modificare e aggiungere prodotti a runtime.
Supporta una configurazione dinamica senza modificare il codice.
Creare un'interfaccia con il metodo di clonazione.
Definire un costruttore che copia i dati da un oggetto esistente.
Implementare il metodo clone() in ciascuna sottoclasse.
Creare, facoltativamente, un registro di prototipi per gestire istanze predefinite e facilitarne la clonazione.
È utilizzato in sistemi che devono creare oggetti complessi in modo efficiente e flessibile, senza accoppiare strettamente il codice alla classe concreta dell'oggetto.
È utile in applicazioni con configurazioni predefinite o a runtime, come nei giochi, nei sistemi di grafica, o in editor di testi e spartiti musicali.
Abstract Factory: Può essere utilizzato in combinazione con Prototype per la creazione di oggetti con configurazioni variabili.
Composite: Può essere usato per strutturare oggetti complessi che vengono clonati come parte di una struttura gerarchica.
Decorator: Può arricchire un oggetto clonabile con funzionalità aggiuntive senza modificarne la struttura originale.
Sottoclassare la classe che crea gli oggetti (Metodo Factory).
Parametrizzare un sistema utilizzando la composizione degli oggetti (Abstract Factory, Builder, Prototype).
Il principale svantaggio del Metodo Factory è che può richiedere la creazione di nuove sottoclassi ogni volta che si vuole cambiare la classe del prodotto, il che può causare cambiamenti a cascata nel sistema.
Il modello basato sulla composizione implica la creazione di un nuovo "oggetto factory" il cui compito è creare oggetti prodotto. Questo approccio evita la necessità di creare sottoclassi per ogni variazione di prodotto.
Nel pattern Abstract Factory, l'oggetto factory è responsabile della produzione di oggetti appartenenti a diverse classi, utilizzando un'unica interfaccia che maschera la variabilità dei prodotti.
Nel pattern Builder, l'oggetto factory costruisce un prodotto complesso in modo incrementale utilizzando un protocollo complesso, suddividendo il processo di creazione in più fasi per una maggiore flessibilità.
Nel pattern Prototype, l'oggetto factory è il prototipo stesso, e il prodotto viene costruito clonando un oggetto prototipo, evitando la necessità di creazione manuale di ogni nuova istanza.
Permette di evitare la creazione di sottoclassi ogni volta che cambia un prodotto.
Fornisce un modo più flessibile per creare oggetti senza modificare il codice esistente.
Supporta una gestione più dinamica della creazione di oggetti complessi.
L'"effetto a cascata" si riferisce al problema che si verifica quando la modifica di una sottoclasse per cambiare il prodotto crea una serie di modifiche necessarie in altre parti del sistema, con possibili ripercussioni su molte altre classi.
Il Metodo Factory richiede la creazione di nuove sottoclassi per ogni variazione del prodotto, mentre i pattern basati sulla composizione utilizzano oggetti factory separati (o prototipi) per creare varianti di prodotto senza modificare direttamente le classi concrete.