Pattern GOF 2

Transcript

Pattern GOF 2
Pattern GOF 2
Laboratorio di Ingegneria del Software
Andrea Bei
Pattern Strutturali
Nome
Adapter
Bridge
Descrizione
Permette a una classe di supportare un'interfaccia anche quando la
classe non implementa direttamente quell'interfaccia.
Disaccoppia un’astrazione dalla sua implementazione in modo che
possano variare in modo indipendente.
Composite
Serve a rappresentare un oggetto complesso in una struttura con
relazione di contenimento. (esempio gerarchie di contenimento nelle
interfacce grafiche)
Decorator
Aggiunge nuove responsabilità ad un oggetto in modo dinamico, è un
alternativa alle sottoclassi per estendere le funzionalità. (In Java è
ampiamente utilizzato negli stream)
Facade
Fornisce un'unica interfaccia di accesso a un sistema complesso evitando
le dipendenze sulla struttura interna del sistema.
Flyweight
Permette di condividere oggetti qualora un loro numero elevato avrebbe
costi proibitivi di efficienza e gestione.
Proxy
Provvede un surrogato di un oggetto per controllarne gli accessi
2
Composite

Problema


Come trattare un
gruppo o una
struttura composta
di oggetti nello
stesso modo
(polimorficamente)
di un oggetto non
composto (atomico)
?
Soluzione

Si definiscano le
classi degli oggetti
composti
(Composite) e
atomici (Leaf) in
modo che
implementino la
stessa interfaccia
(Component)
3
Composite esempio

Problema

Come gestire più politiche di
prezzo su uno stesso cliente
? es:





{
...
return pricingStrategy.getTotal( this )
}
Component
Sale
date
...
10 % sconto per anziani
50 % di sconto per vendite
superiori di 500 dollari
....
1
Leaf
Leaf
PercentageDiscount
PricingStrategy
AbsoluteDiscount
OverThreshold
PricingStrategy
1..*
strategies
Composite
Composite
PricingStrategy
percentage : float
getTotal( Sale ) : Money
Soluzione
Si definisca una Composite
di Strategy
 Si definiscano due
sottoclassi di questa che
applicano due strategie
composte
«interface»
ISalePricingStrategy
pricingStrategy getTotal( Sale ) : Money
getTotal()
...
Si possono gestire in modo
che sia conveniente per il
cliente o per il negoziante
La Composite
All composites maintain a list of
mantiene
laTherefore,
lista
contained strategies.
define
a
common
superclass
delle Strategie (una
CompositePricingStrategy that
lista
dilistoggetti
defines this
(named strategies).
Component)
discount : Money
threshold : Money
add( ISalePricingStrategy )
getTotal( Sale ) : Money
getTotal( Sale ) : Money



la migliore per il cliente
la migliore per il negoziante
{
return sale.getPreDiscountTotal() *
percentage
}
CompositeBestForCustomer
PricingStrategy
getTotal( Sale ) : Money
{
lowestTotal = INTEGER.MAX
for each ISalePricingStrategy strat in pricingStrategies
{
total := strat.getTotal( sale )
lowestTotal = min( total, lowestTotal )
}
return lowestTotal
}
CompositeBestForStore
PricingStrategy
getTotal( Sale ) : Money
4
Bridge


Problema: come separare un’astrazione
dalla sua implementazione, in modo che
entrambe possano variare
indipendentemente.
Soluzione:separare l’astrazione
dall’implementazione legando oggetti della
seconda a quelli della prima, tramite un
relazione di aggregazione.
5
Bridge (esempio)
L’astrazione Matrix ha due implementazioni:
1. come matrice sparsa (contenente solo i valori diversi da 0)
2. come matrice completa
Una Matrix può essere implementata con una Collection (un’altra astrazione) che può essere a sua volta
implementata con
1. Vector o
2. ArrayList
6
Bridge
Schema del Pattern
7
Bridge
8
Decorator



Problema:come aggiungere dinamicamente responsabilità ad un
oggetto ?
Soluzione: si creino delle classi wrapper (Decorator) che racchiudono
(decorano) gli oggetti ai quali si vuole aggiungere le nuove
responsabilità.
Oggetti “decorati”” e wrapper devono implementare una interfaccia
comune, in modo che


l’applicazione possa continuare ad interagire con gli oggetti decorati
attraverso l’interfaccia comune
sia possibile l’applicazione di un Decorator ad un altro oggetto già decorato,
ottenendo in questo modo la sovrapposizione di più responsabilità.
Obj
Decorator 1
Decorator 2
Es:
•
Decorator e oggetti da decorare implementano
la stessa interfaccia in cui è definito il metodo
m1
•
Ogni “decorazione” aggiunge responsabilità al
metodo m1 definito in obj
•
Il metodo m1 di ogni decorator racchiude la
logica del decorator stesso ed infine invoca il
metodo m1 del decorator contenuto fino ad
arrivare all’oggetto OBJ
9
Decorator: esempio

Problema:




una azienda è costituita da Employee che afferiscono ad uffici di
appartenenza
un Engineer è un tipo di Employee
un Engineer può assumere l’incarico di capoufficio (AdministrativeManger) o
di capoprogetto (ProjectManager)
un Engineer può essere capoufficio ed anche capoprogetto di più progetti
L’interfaccia comune serve a garantire la
relazione di aggregazione
La classe
concreta di
base
•Le classi di tipo ResponsibleWorker
(AdministrativeManager e
ProjectManager) sono i Decorator
•Engineer può essere “decorato” con
diverse responsabilità ovvero con diverse
classi di tipo ResponsibleWorker
10
Decorator
Schema del pattern
11
Decorator
12
Decorator
"D.O.S.- Doors
Operating System"
“EveryoneLoggedTo
Internet
Explorer"
Engineer
AdministrativeManager
ProjectManager
ProjectManager
13
Facade



Problema:come fornire una interfaccia unificata per un insieme di
interfacce di un sottosistema, rendendo più facile l’uso di quest’ultimo.
Soluzione: si crei una classe Facade che mostri una interfaccia
semplificata al cliente e si faccia carico di gestire le complessità delle
iterazioni tra le interfacce e le classi del sottosistema
E’ usato nel pattern architetturale layers
Schema del pattern
// Layer 1
class Object1Layer1 {}
class Object2Layer1 {}
...
class ObjectNLayer1 {}
interface FacadeLayer1 {
public void method() {
// use ObjectNLayer1
}
}
// Layer 2
class ObjectNLayer2 {
facadeLayer1.method();
}
14
Facade (esempio)

Problema: in Java per prendere un input dalla tastiera è necessario
scrivere il codice seguente.
Come semplificare questa operazione ?
 Come evitare che il programmatore sia costretto a gestire BufferedReader,
InputStreamReader, System, String, Integer, Double, Float, ecc.


Soluzione:

Creare una classe Facade
ConsoleReader che offre
una interfaccia semplice con
le operazioni getString,
getInteger, getDouble e
nasconde al cliente le chiamate
alle classi di cui sopra
15
Facade
16
Flyweight



Problema:come gestire un numero elevato di oggetti dello stesso tipo in
modo efficiente in termini di memoria
Soluzione: si creino dei “flyweight” ovvero degli oggetti condivisi che
possono essere utilizzati in diversi contesti contemporaneamente, in
quanto in questi contesti condividono lo stato interno, e quello che non
è interno si può esternalizzare.
Esempio: Un sistema di controllo deve gestire in tempo reale una coda
di eventi (Event). Gli eventi, rappresentati come oggetti, devono essere
analizzati da un controllore, che deve reagire opportunamente a
seconda dell’evento
Senza FlyWeight
Con FlyWeight
17
Flyweight (esempio)
18
Flyweight
Schema del Pattern
19
Proxy

Problema: come introdurre un surrogato, o
rappresentante di un oggetto. Ad esempio quando
l’accesso all’oggetto richiede tempo (è
computazionalmente pesante) e si vogliono
implementare politiche di caching

Soluzione:si implementi una classe Proxy che offra
la stessa interfaccia della classe originale e che sia
in grado di risolvere le richieste più “semplici”. Solo
le richieste più complesse vengono inoltrate alla
classe originale
20
Proxy

Esempio: FileHandler (gestisce operazioni su un file di testo)
Proxy: il proxy fa un
caching dell’ultima riga
acceduta
Inefficienza: per
accedere ad una riga
del file occorre scandire
tutto il file fino alla riga
voluta anche se la riga è
stata acceduta nella
richiesta precedente
21
Proxy
Schema del Pattern
22
Proxy
23