Upload
others
View
1
Download
0
Embed Size (px)
Citation preview
Design Patterns Parte 2
2
Builder Design Pattern
Separa la costruzione di un oggetto complesso dalla rappresentazione delle parti che lo compongono: lo stesso processo di costruzione è riusato per creare oggetti che hanno differenti forme di rappresentazione.
L’interfaccia Builder specifica i metodi necessari per creare le parti di cui è composto un oggetto complesso. Spesso tali
metodi sono Factory Methods.
Partecipanti nel Builder Pattern
Builder ConcreteBuilder Director Product
3
Product
ConcreteBuilder
buildPartA() buildPartB() getResult()
Directorconstruct()
BuilderbuildPartA()buildPartB()
Client
for all parts in structure { builder->buildPart() }
Struttura dei Partecipanti
4
Diagrammi di Sequenza
5
Quando si usa il Builder Pattern• Quando l’algoritmo per costruire un oggetto complesso dovrebbe rimanere indipendente dalle
parti che lo compongono e da come tali parti sono rappresentate ed assemblate. • Quando la costruzione di un oggetto complesso deve consentire la specifica di
rappresentazioni e modelli dei dati alternative e tali scelte devono essere differibili a tempo di esecuzione.
• Quando si costruiscono oggetti compositi che hanno una struttura interna non elementare.
Conseguenze
Importante: Il Builder Design Pattern fornisce controllo a tutti i livelli del processo di
costruzione.
• Seleziona la rappresentazione interna di un oggetto a tempo di creazione • Disaccoppia il codice che definisce la struttura di un oggetto da quello che crea le
singole parti che lo compongono
6
Design PatternsPatterns strutturali (28/64)
Introduzione
! Riguardano il modo in cui classi ed oggetti sono legati tra loro in strutture più grandi e/o complesse.
! I pattern strutturali per le classi usano l'ereditarietà per comporre insieme diverse interfacce o implementazioni.
! I pattern strutturali per gli oggetti descrivono modi di comporre oggetti che realizzano nuove funzionalità.
! I pattern strutturali utilizzano ereditarietà per comporre interfacce o implementazioni: es. è possibile utilizzare un pattern strutturale per combinare più classi. Tale pattern risulta utile per rendere interoperabili librerie sviluppate in maniera indipendente l’una dall’altra.
Iniziamo con: ! Adapter (class) "! Adapter (object)
7
DP : Adapter (Strutturale)"
■ Nome: Adapter "
■ Sinonimo : Wrapper "
■ Scopo : Converte l’interfaccia di una classe in un’altra interfaccia, attesa da un cliente ( quindi permette la
cooperazione di classi che altrimenti avrebbero interfacce incompatibili)
"■ Motivazione : In alcune circostanze non si potrebbe utilizzare
una classe già esistente e collaudata solo perché quest’ultima non comunica più con una interfaccia specializzata richiesta da
un’applicazione.
Design PatternsPatterns strutturali (29/64)
8
DP : Adapter■ Struttura :
Design PatternsPatterns strutturali (30/64)
9
DP : Adapter■ Struttura ( alternativa):
Design PatternsPatterns strutturali (31/64)
10
Class Adapter Structure
Varia
nt 1
: Im
plem
enta
tion
inhe
ritan
ce
Varia
nt 2
: A
ssoc
iatio
n
Design PatternsPatterns strutturali (32/64)
Object Adapter Structure
11
DP : Adapter■ Esempio: un editor grafico usa una classe Shape per editare e
visualizzare gli oggetti grafici. "
■ Il progettista possiede una classe riusabile TextView per editare e visualizzare testo.
"■ Purtroppo TextView non sa nulla di Shape.
"■ Possiamo però definire una nuova classe TextShape che
incapsuli TextView e adatti la sua interfaccia a quella di Shape.
Design PatternsPatterns strutturali (33/64)
12
DP : Adapter■ Esempio concreto di adattatore
Design PatternsPatterns strutturali (34/64)
13
DP : Adapter"
■ Applicabilità: Adapter puo essere utilizzato :
1. Se si vuole utilizzare una classe esistente la cui interfaccia sia incompatibile
2. Se si vuole creare una classe (riusabile) che dovrà collaborare con classi non prevedibili al momento della
sua creazione 3. Se si vuole riusare un insieme di sottoclassi esistenti,
ma è scomodo adattare l’interfaccia creando una sottoclasse per ciascuna: meglio creare un adattatore
Design PatternsPatterns strutturali (35/64)
14
Adapter! Partecipanti :
– Target : definisce l’interfaccia specializzata usata dal client (Es.
Shape) – Client : collabora con oggetti conformi
all’interfaccia target (Es. DrawEditor)
– Adaptee : definisce un ‘interfaccia che deve essere resa conforme (Es.
TextView) – Adaptor : adatta l’interfaccia di adaptee
all’interfaccia Target (Es. TextShape)
Design PatternsPatterns strutturali (36/64)
15
Esempio codice C++class Shape { public: Shape(); virtual void BoundingBox(Point& bottomLeft, Point& topRight) const; virtual Manipulator* CreateManipulator() Const; }; ""class TextView { public: TextView(); void GetOrigin(Coord& x, Coord& y) const; void GetExtent(Coord& width, Coord& height) const; virtual bool IsEmpty() const; };
Design PatternsPatterns strutturali (39/64)
16
Esempio codice C++class TextShape: public Shape, private TextView { public: TextShape(); virtual void BoundingBox( Point& bottomLeft, Point& topRight) const; virtual bool IsEmpty() const; virtual Manipulator* CreateManipulator() Const; }; // Implementazione TextShape::BoundingBox void TextShape::BoundingBox(Point& bottomLeft, Point& topRight) const { Coord bottom, left, width, height; GetOrigin(bottom,left); GetExtent(width,height); bottomLeft=Point(bottom,left); topRight=Point(bottom+height,left+width) };
Design PatternsPatterns strutturali (40/64)
Ereditarietà privata e multipla
17
/* New Adaptor class */ class MyStringComparator implements Comparator { /* ... */ int compare (Object o1, Object o2) { int result; if (o1.greaterthan(o2)) { result = 1;
} else if (o1.equals(o2)) { result = 0;
} else { result = -1;
} return result;
} }
Adapter Example II
18
Design PatternsPatterns comportamentali (44/64)
Introduzione
! I behavioral pattern riguardano la definizione/gestione di algoritmi e le assegnazioni di responsabilità tra le diverse classi ed oggetti: essi descrivono le modalità di comunicazione tra gli oggetti, oltre che le relazioni tra gli stessi.
! I behavioral class patterns utilizzano l’ereditarietà per distribuire comportamenti tra diverse classi
! I behavioral object patterns utlizzano composizione piuttosto che ereditarietà ! In linea del tutto generale, si utilizza un behavioral pattern per incapsulare
comportamenti. I behavioral patterns che tratteremo oggi sono i seguenti: ! Observer = Definisce una relazione di dipendenza tra un oggetto “osservato” e un
insieme qualsiasi di “osservatori”. Essi vengono notificati di ogni cambiamento di stato dell'oggetto osservato.
19
! Intento: Definire una relazione uno a molti tra oggetti, in modo che quando un oggetto cambia stato, ciò è notificato a tutti gli oggetti dipendenti
! Alias: Dependant, Publish-Subscribe ! Motivazioni: Es. consideriamo i grafici prodotti da uno spreadsheet.
Cambiando i dati di origine, i grafici si aggiornano automaticamente. L’interazione avviene tra un subject ed un numero qualsiasi di observer dipendenti, che vengono notificati quando cambia lo stato del subject.
"! Applicabilità: l’Observer andrebbe usato quando:
– Un’astrazione ha due aspetti, una dipendente dall’altra, e si desidera incapsulare le due astrazioni in oggetti separati;
– Se cambiamenti ad un oggetto richiedono di cambiarne altri, senza sapere quali;
– Quando un oggetto deve essere in grado di notificare qualcosa ad un’altro oggetto non noto a priori.
""
Design PatternsPatterns comportamentali (45/64)
Observer (1/5)
20
Struttura:
Design PatternsPatterns comportamentali (46/64)
Observer (2/5)
21
! Collaborations: – Il ConcreteSubject notifica ai propri Observers quando ha luogo un cambiamento
che porterebbe l’Observer in uno stato inconsistente. – Dopo essere stato informato del cambiamento, il ConcreteObserver effettua una
query sul Subject per richiedere informazioni, e le utilizza poi per riallineare il proprio stato con quello del Subject stesso.
""
Design PatternsPatterns comportamentali (47/64)
Observer (3/5)
22
"■ Conseguenze:
! Accoppiamento astratto tra Subject e Observer: un Subject sa che ha una lista di Observer, conformi ad un’interfaccia astratta (AbstractObserver), ma non è a conoscenza delle classi concrete degli stessi;
"! Supporto alla comunicazione di tipo multicast; "! Aggiornamenti inattesi: se le interdipendenze non sono ben
formate, possono verificarsi aggiornamenti a cascata indesiderati.
"
Design PatternsPatterns comportamentali (48/64)
Observer (4/5)
23
Design PatternsPatterns comportamentali (49/64)
Observer (5/5)Implementazione:
! Intento: Incapsulare una richiesta in un oggetto, in modo tale da parametrizzare i client rispetto a richieste differenti, consentendo operazioni come accodamento, logging e undo.
! Noto come: Action, Transaction ! Motivazioni: Oggetti di un toolkit possono effettuare richieste
trasformando le richieste stesse in oggetti. La “chiave” del pattern è la classe Command, che dichiara un’interfaccia per l’esecuzione delle operazioni (metodo Execute()). Le classi ConcreteCommand specificano la coppia azione-ricevente implementando tale metodo, e immagazzinando il ricevente in una variabile di istanza.
Design PatternsPatterns strutturali
Command (1/9)
Design PatternsPatterns strutturali
Command (2/9)
Come è possibile notare, i menu possono essere implementati agevolmente con tale pattern. Ciascuna scelta del Menu è un’istanza della classe MenuItem. L’Application crea il Menu e tiene traccia dei Documents aperti. Ciascun MenuItem è associato ad un’istanza di una classe ConcreteCommand.
Design PatternsPatterns strutturali
Command (3/9)
Design PatternsPatterns strutturali
Command (4/9)
! Applicabilità: Il Command è utile per: – Parametrizzare oggetti rispetto ai comandi da eseguire (ciò nei
linguaggi procedurali spesso avviene per mezzo di una callback, ovvero una funzione registrata in un certo punto per poi essere richiamata successivamente);
– Specificare, accodare ed esegure richieste in tempi diversi; – Supportare l’undo: l’operazione di Execute può mantenere lo stato
per annullare il proprio effetto; – Supppotare il logging dei comandi in modo da consentire il redo in
caso di crash del sistema; – Eseguire transazioni atomiche.
Design PatternsPatterns strutturali
Command (5/9)
Struttura:
Design PatternsPatterns strutturali
Command (6/9)
! Collaborations: – Il client crea un ConcreteCommand e specifica il
proprio ricevente; – L’Invoker immagazzina il ConcreteCommand; – Il ConcreteCommand invoca operazioni sul
ricevente per eseguire le richieste.
Design PatternsPatterns strutturali
Command (7/9)
Collaborations:
Design PatternsPatterns strutturali
Command (8/9)
! Conseguenze: – Il Command disaccoppia l’oggetto che invoca l’operazione
da quello che la esegue; – Un Command può essere manipolato o esteso come
qualsiasi altro oggetto; – E’ possibile assemblare Commands creando dei comandi
composti; – Aggiungere nuovi Command risulta semplice, e non
richiede modifiche alle classi esistenti.
Design PatternsPatterns strutturali
Command (9/9)