Estratto del documento

1

FACTORY METHOD

Scopo: CREAZIONALE

Raggio d’azione: BASATO SU CLASSI

Si puo chiamare anche “Virtual Constructor”

Definisce un’interfaccia per la creazione di un oggetto, lasciando alle

sottoclassi la decisione sulla classe concreta che sarà instanziata.

Consente di deferire la creazione di un oggetto alle sottoclassi.

I framework utilizzano classi astratte per definire e mantenere le relazioni tra

gli oggetti e spesso sono anche responsabili della creazione di questi oggetti.

Si consideri un framework per applicazioni in grado di presentare più

documenti agli utenti.

La classe Application è responsabile della gestione di oggetti conformi

all’interfaccia Document e della loro creazione. Application sa solo quando

dovrà creare un nuovo documento ma non di che tipo né come dovrà farlo. La

responsabilità è spostata all’esterno del framework: le sottoclassi di Application

devono fornire l’implementazione del metodo factory createDocument() in

modo da restituire un’istanza della classe appropriata.

-Struttura

Product (Document) : definisce l’interfaccia degli oggetti creati dal metodo

factory.

ConcreteProduct(MyDocument): implementa l’interfaccia Product.

Creator(Application): dichiara il metodo factory, nell’esempio protetto, che

restituisce un oggetto di tipo Product. Può invocare createProduct() per creare

un prodotto.

ConcreteCreator(MyApplication): sovrascrive createProduct in modo da

restituire una specifica istanza di ConcreteProduct. 2

-Conseguenze

Elimina la necessità di riferirsi a classi dipendenti dall’applicazione all’interno

del codice del framework.

Gli utilizzatori potrebbero essere costretti a definire sottoclassi di Creator per

creare un particolare oggetto ConcreteProduct.

Fornisce un punto di aggancio per le sottoclassi per la produzione di una

versione specializzata di un prodotto.

Connette gerarchie di classi parallele. Il metodo factory potrebbe essere

invocato da oggetti diversi dal Creator, vedi esempio.

-Gerarchie classi parallele

Figure è il tipo di base di figure geometriche manipolabili graficamente.

La logica di manipolazione può essere complicata e diversa da figura a figura.

Si può attribuire la responsabilità di implementare una logica di manipolazione

ad oggetti separati introducendo il tipo Manipulator.

Si ottiene una gerarchia parallela a quella delle Figure. Ogni classe che

implementa Figure ha il proprio metodo Figure, ha il proprio metodo factory per

creare l’apposito Manipulator.

Pattern correlati: Abstract Factory 3

BUILDER

Scopo: CREAZIONALE

Raggio d’azione: BASATO SU OGGETTI

Separare la costruzione di un oggetto complesso dalla sua rappresentazione, in

modo che lo stesso processo di costruzione possa essere utilizzato per creare

rappresentazioni diverse. Riutilizzare lo stesso tipo di creazione per diverse

rappresentazioni.

- Struttura

BuilderIF: specifica l’interfaccia astratta che crea le parti dell’oggetto Product

ConcreteBuilder: costruisce e assembla le parti del prodotto implementando

l’interfaccia Builder; definisce e tiene traccia della rappresentazione che crea.

Director: Costruisce l’oggettto utilizzando l’interfaccia Builder.

Product: rappresenta l’oggetto complesso e include le classi che definiscono le

parti che lo compongono, includendo le interfacce per assemblare le parti nel

risultato finale.

- Interazioni 4

Il client crea l’oggetto Director e lo configura tramite l’oggetto Builder

desiderato.

Il Director informa il Builder ogni volta che una parte di Product deve essere

costruita.

Il Builder riceve e gestisce le richieste dl Director e aggiunge le parti al Product.

Il client ottiene dal Builder il Product creato.

- Conseguenze

Consente di variare la rappresentazione interna di un prodotto

 L’interfaccia del Builder consente di nascondere la rappresentazione, la

struttura interna dell’oggetto Product e il processo di costruzione. Per

modificare la rappresentazione del Product basta definire un nuovo tipo

di Builder.

Isola il codice per la costruzione e la rappresentazione

 Migliora la modularizzazione incapsulando il modo di costruire e

rappresentare un oggetto complesso. Per i client non è necessario

conoscere le classi che definiscono la struttura interna del prodotto

perché esse non appaiono nell’interfaccia Builder.

Consente un migliore controllo del processo di produzione

 A differenza di altri pattern creazionali che costruiscono il prodotto nella

sua interezza, in questo caso il prodotto viene costruito passo dopo passo

sotto il controllo del Director.

- Costruttori Telescopici

I metodi factory statici e i costruttori condividono una limitazione: non scalano

bene quando ci sono molti parametri. Di solito la soluzione più adottatta

consiste nel fornire più costruttori con le varie combinazioni di parametri

presenti. I costruttori telescopici funzionano ma il codice cliente risulta difficile

da scrivere e ancora più difficile da leggere. Per capire che parametro è,

bisogna calcolare la sua posizione.

- Soluzione JavaBeans

Si introduce un costruttore senza parametri per creare un oggetto. I parametri

richiesti si specificano invocando gli appositi metodi setter. Tuttavia siccome il

processo di costruzione è diviso in varie chiamate l’oggetto creato potrebbe

trovarsi in uno stato inconsistente. La classe non ha modo di verificare la

consistenza dei parametri. Preclude la possibilità di rendere gli oggetti della

classe immutabili.

La soluzione migliore consiste nel ricorrere all’uso del pattern Builder.

La classe Nutrition Facts definisce un builder come inner class statica. La classe

Builder riproduce nei suoi campi quelli della classe NutritionFacts.

La classe Builder introduce un metodo per ciascun parametro opzionale. Questi

metodi settano il parametro e restituiscono il builder stesso. Il metodo build

crea l’oggetto fornendo atomicamente tutti i parametri per mezzo del builder.

Si noti che la classe NutritionFacts è immutabile. Ecco come appare il codice

client:

NutritionFacts cocaCola = new 5

NutritionFacts.Builder(240,8).calories(100).sodium(35).carbohydrate(27).build()

;

Questo codice è molto più facile da leggere e da scrivere.

Il Builder può imporre degli invarianti sui parametri durante l’invocazione di

build(). Un singolo builder può essere utilizzato per creare più oggetti. Il builder

può riempire alcuni campi automaticamente come ad esempio il numero

seriale che si incrementa automaticamente ad ogni creazione.

BRIDGE

Scopo: STRUTTURALE

Raggio di azione : BASATO SU OGGETTI

Disaccoppia un’astrazione dalla sua implementazione in modo che le due

possano variare indipendentemente l’una dall’altra.

Altri nomi: Handle/Body

Quando un’astrazione può avere una tra più implementazioni possibili, in

genere si risolve il problema ricorrendo all’ereditarietà.

L’astrazione viene definita da un’interfaccia o da una classe astratta e le

sottoclassi concrete la implementano in modi differenti.

Tale approccio non è flessibile poiché l’ereditarietà lega un’implementazione ad

un’astrazione in modo permanente. Ciò rende difficile modificare, estendere e

riusare astrazioni ed implementazioni in modo indipendente.

- Applicabilità

Si vuole evitare un legame permanente tra un’astrazione e la sua

implementazione, come nel caso in cui l’implementazione deve poter essere

selezionata e/o modificata durante l’esecuzione.

Si vuole avere la possibilità di estendere sia le astrazioni che le

implementazioni per mezzo dell’ereditarietà. Tramite Bridge è possibile

combinare le astrazioni e le implementazioni in vario modo e di estendere le

une indipendentemente dalle altre.

I cambiamenti nell’implementazione di un’astrazione non devono avere

impatto sui client.

Si vuole condividere una stessa implementazione fra più oggetti nascondendo

questa condivisione ai client.

- Struttura 6

Abstraction: specifica l’interfaccia dell’astrazione. Mantiene un riferimento ad

un oggetto di tipo Implementor.

RefinedAbstraction: Estende l’interfaccia definita da Abstraction.

Implementor: definisce l’interfaccia per le classi che implementano

l’astrazione. Non deve corrispondere esattamente all’interfaccia di Abstraction:

Implementor fornisce le operazioni base, mentre Abstraction definisce

operazioni di più alto livello implementate sfruttando quelle di base.

ConcreteImplementor: definisce un’implementazione concreta

dell’interfaccia Implementor.

- Conseguenze

Disaccoppiamento tra interfaccia e implementazione

 Un’implementazione non è più legata in modo permanente a

un’interfaccia. L’implementazione di un'astrazione può essere

configurata durante l’esecuzione. Il disaccoppiamento tra Abstraction ed

Implementor elimina la dipendenza dell’implementazione a tempo di

compilazione. Ciò aiuta ad ottenere una struttura stratificata del

sistema.

Maggiore estensibilità

 Le gerarchie di classi Abstract e Implementor possono essere estese

indipendentemente.

Mascheramento dei dettagli dell’implementazione ai client

 I client non devono preoccuparsi dei dettagli implementativi, quali per

esempio la condivisione di oggetti Implementor e il relativo meccanismo

di conteggio dei riferimenti.

Gestione delle risorse umane del progetto

 Divisione di compiti: una parte si occupa dell’astrazione, l’altra della

parte concreta. La modularità di questo pattern permette quindi di

dividere il lavoro e quindi di lavorare in parallelo.

Pattern correlati: Abstract Factory può essere utilizzato per creare e

configurare un particolare Bridge.

- Adapter vs Bridge

Il pattern Adapter ha lo scopo di far cooperare tra di loro classi non correlate

dopo che sono state progettate. 7

Il pattern Bridge è utilizzato all’inizio di un progetto per consentire ad astrazioni

ed implementazioni di variare in modo indipendente. 8

FACADE

Scopo: STRUTTURALE

Raggio d’azione: BASATO SU OGGETTI

Fornire un’interfaccia unificata per un insieme di interfacce presenti in un

sottosistema.

Facade definisce un’interfaccia di livello più alto che rende il sistema più

semplice da utilizzare.

- Struttura

Facade (Message Creator): conosce le classi nel sottosistema che sono

responsabili di gestire una richiesta.

Classi del sottosistema (Message, MessageBody, Attachment):

implementano le funzionalità del sottosistema. Non hanno alcuna conoscenza

dell’esistenza del Facade: non hanno alcun riferimento ad esso.

- Conseguenze

Nasconde ai client i componenti del sottosistema, riducendo il numero

 degli oggetti con cui i client interagiscono

Promuove un basso accoppiamento tra un sottosistema ed i suoi client. I

 componenti del sottosistema sono molto accoppiati tra di loro (alta

coesione interna). La riduzione delle dipendenze è di fondamentale

importanza nei sistemi di grandi dimensioni.

In particolare, riduce le dipendenze di compilazione: se le classi del

 sottosistema sono modificate non è necessario ricompilare il codice del

client.

Non impedisce alle applicazioni client di utilizzare le classi del

 sottosistema qualora sia necessario

Pattern correlati: Abstract Factory , Mediator, Singleton 9

Abstract Factory

Scopo: CREAZIONALE

Raggio d’azione: BASATO SU OGGETTI

Altri nomi: Kit

Consente di creare famiglie di oggetti correlati, fornisce una interfaccia comune

sensza specificare classi concrete.

- Applicabilità

Un sistema deve essere indipendente dalla modalità di creazione,

composizione e rappresentazione dei suoi prodotti.

Un sistema deve poter essere configurato scegliendo tra più famiglie di

prodotti.

Esistono famiglie di oggetti correlati, progettati per essere usati insieme.

Si intende fornire una libreria di classi, rivelando le interfacce e nascondendo le

implementazioni.

AbstractFactory: dichiara un’interfaccia per le operazioni di creazione di

oggetti prodotto astratti.

ConcreteFactory: implementa le operazioni degli oggetti prodotto concreti.

Product: dichiara un’interfaccia per un tipo di prodotti.

ConcreteProduct: implementa l’interfaccia Product definendo un oggetto

prodotto creato dalla corrispondente factory concreta.

- Conseguenze

Isola le classi concrete. Poiché una classe factory incapsula il

 processo di creazione dei prodotti concreti rende i clienti indipendenti

dalle classi utilizzate per la loro implementazione. I clienti conoscono

solo le interfacce dei prodotti.

Consente di cambiare in modo semplice la famiglia di prodotti

 utilizzata. È possibile ottenere una configurazione di oggetti diversi

semplicemente cambiando il tipo di factory concreta utilizzata.

Promuove la coerenza nell’utilizzo dei prodotti.

 L’aggiunta del supporto a nuove tipologie di prodotti è

 difficile. L’aggiunta di un nuovo tipo di prodotto comporta una 10

modifica dell’interfaccia AbstractFactory e , di conseguenza, di tutte le

classi che la implementano.

- Implementazione

Factory come Singleton

 Un’applicazione tipicamente richiede una singola istanza di factory

concreta per ciascuna famiglia di prodotti. Tale istanza è di solito

ottenuta per mezzo del pattern Singleton.

Creazione dei prodotti

 Abstact Factory definisce un’interfaccia per la creazione di prodotti

mentre la responsabilità della creazione effettiva delle istanze

compete alle classi ConcreteProduct. Ciò può essere realizzato in vari

modi:

- introduzione di un metodo Factory per ogni prodotto.

- Ricorso al pattern Prototype: in questo caso la factory concreta

viene inizializzata con un’istanza prototipo di ciascun prodotto della

famiglia. La creazione dei prodotti avviene per clonazione dei

prototipi. 11

COMPOSITE

Scopo: STRUTTURALE

Raggio d’azione: BASATO SU OGGETTI

Comporre oggetti in strutture ad albero per rappresentare gerarchie parte-tutto

e consentire ai client di trattare oggetti singoli e composizioni in modo

uniforme

- Motivazione

Applicazioni quali editor grafici vettoriali o ambienti per la progettazione di

circuiti consentono agli utenti di costruire diagrammi complessi a partire da

semplici componenti.

Componenti semplici possono essere raggruppati per costruire componenti più

complessi che possono a loro volta essere utilizzati come parti di componenti

ancor più complessi.

Solitamente si introducono alcune classi per modellare gli oggetti semplici ed

altre per rappresentare gli oggetti ottenuti per composizione.

Il pattern Composite introduce un’interfaccia comune per gli oggetti semplici e

per quelli compositi in modo che il codice cliente li possa trattare

uniformemente.

Composite: dichiara l’interfaccia per gli oggetti componibili. Può essere una

classe astratta che fornisce un’implementazione di default per i metodi di

gestione dei componenti figli. Introduce (opzionale) un metodo per accedere al

componente genitore.

Leaf: rappresenta gli oggetti primitivi i quali non hanno figli.

Composite: definisce il comportamento dei componenti che hanno figli.

Memorizza i componenti figli e implementa i relativi metodi introdotti

dall’interfaccia Component.

- Conseguenze

Definisce gerarchie di classi costituite da oggetti primitivi ed oggetti

 compositi. Gli oggetti primitivi possono essere composti per dare origine

ad oggetti più complessi. Il codice cliente tratta oggetti compositi e

primitivi in modo differente. 12

Il codice cliente non sa e non è interessato a saperlo se sta utilizzando un

 oggetto primitivo o composito.

Rende semplice l’aggiunta di nuovi tipi di componenti senza influenzare il

 codice cliente.

L’interfaccia Component potrebbe essere troppo generale. Può essere

 necessario vincolare un particolare tipo di oggetto composito ad avere

solo determinati tipi di componenti. Il compilatore non può garantire tale

vincolo, per cui è necessario ricorrere a verifiche a tempo di esecuzione.

- Implementazione

Riferimenti al genitore

 Fare in modo che ciascun componente conservi il riferimento al genitore

può semplificare le operazioni di gestione e di visita della struttura

composita. È importante fare in modo che tutti i figli di un oggetto

composito riferiscano a esso stesso come genitore. Il modo più semplice

per garantire ciò consiste nel modificare il riferimento al genitore

contestualmente alle operazioni di aggiunta e rimozione dei figli.

Massimizzazione dell’Interfaccia Component

 Al fine di rendere uniforme l’interfaccia dei componenti, Component

potrebbe includere alcune operazioni che non hanno senso per i

componenti primitivi. Ciò è in contrasto con il principio secondo cui una

classe astratta dovrebbe includere solo le operazioni che hanno senso

per le sottoclassi.

Dichiarazione di metodi e gestione dei figli

 Una scelta importante nell’implementazione del pattern riguarda il punto

in cui sono definite le operazioni di gestione dei figli. Nell’esempio esse

sono dichiarate da Component, un’alternativa sarebbe quella di

introdurle nella classe composite.

- la prima scelta garantisce l’uniformità di interfaccia ma, di contro, se

invocate su componenti primitivi tali operazioni falliscono o non hanno

effetto.

- nel secondo caso ci sono maggiori garanzie a tempo di compilazione ma

si perde in termini di trasparenza. 13

VISITOR

Scopo: COMPORTAMENTALE

Raggio d’azion

Anteprima
Vedrai una selezione di 17 pagine su 76
Preparazione completa Ingegneria del software Pag. 1 Preparazione completa Ingegneria del software Pag. 2
Anteprima di 17 pagg. su 76.
Scarica il documento per vederlo tutto.
Preparazione completa Ingegneria del software Pag. 6
Anteprima di 17 pagg. su 76.
Scarica il documento per vederlo tutto.
Preparazione completa Ingegneria del software Pag. 11
Anteprima di 17 pagg. su 76.
Scarica il documento per vederlo tutto.
Preparazione completa Ingegneria del software Pag. 16
Anteprima di 17 pagg. su 76.
Scarica il documento per vederlo tutto.
Preparazione completa Ingegneria del software Pag. 21
Anteprima di 17 pagg. su 76.
Scarica il documento per vederlo tutto.
Preparazione completa Ingegneria del software Pag. 26
Anteprima di 17 pagg. su 76.
Scarica il documento per vederlo tutto.
Preparazione completa Ingegneria del software Pag. 31
Anteprima di 17 pagg. su 76.
Scarica il documento per vederlo tutto.
Preparazione completa Ingegneria del software Pag. 36
Anteprima di 17 pagg. su 76.
Scarica il documento per vederlo tutto.
Preparazione completa Ingegneria del software Pag. 41
Anteprima di 17 pagg. su 76.
Scarica il documento per vederlo tutto.
Preparazione completa Ingegneria del software Pag. 46
Anteprima di 17 pagg. su 76.
Scarica il documento per vederlo tutto.
Preparazione completa Ingegneria del software Pag. 51
Anteprima di 17 pagg. su 76.
Scarica il documento per vederlo tutto.
Preparazione completa Ingegneria del software Pag. 56
Anteprima di 17 pagg. su 76.
Scarica il documento per vederlo tutto.
Preparazione completa Ingegneria del software Pag. 61
Anteprima di 17 pagg. su 76.
Scarica il documento per vederlo tutto.
Preparazione completa Ingegneria del software Pag. 66
Anteprima di 17 pagg. su 76.
Scarica il documento per vederlo tutto.
Preparazione completa Ingegneria del software Pag. 71
Anteprima di 17 pagg. su 76.
Scarica il documento per vederlo tutto.
Preparazione completa Ingegneria del software Pag. 76
1 su 76
D/illustrazione/soddisfatti o rimborsati
Acquista con carta o PayPal
Scarica i documenti tutte le volte che vuoi
Dettagli
SSD
Ingegneria industriale e dell'informazione ING-INF/05 Sistemi di elaborazione delle informazioni

I contenuti di questa pagina costituiscono rielaborazioni personali del Publisher andrea.dellosso.1 di informazioni apprese con la frequenza delle lezioni di Ingegneria del software e studio autonomo di eventuali libri di riferimento in preparazione dell'esame finale o della tesi. Non devono intendersi come materiale ufficiale dell'università Università della Calabria o del prof Furfaro Angelo.
Appunti correlati Invia appunti e guadagna

Domande e risposte

Hai bisogno di aiuto?
Chiedi alla community