Design Patterns Parte 2 · 2 Builder Design Pattern Separa la costruzione di un oggetto complesso...

Post on 16-Aug-2020

1 views 0 download

Transcript of Design Patterns Parte 2 · 2 Builder Design Pattern Separa la costruzione di un oggetto complesso...

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)