Sei sulla pagina 1di 32

Introduzione ai design pattern

Cosa sono i design pattern


I problemi incontrati nello sviluppare grossi progetti software sono spesso ricorrenti e prevedibili. I design pattern sono schemi utilizzabili nel progetto di un sistema Permettono quindi di non inventare da capo soluzioni ai problemi gia` risolti, ma di utilizzare dei mattoni di provata efficacia Inoltre, un bravo progettista sa riconoscerli nella documentazione o direttamente nel codice, e utilizzarli per comprendere in fretta i programmi scritti da altri
forniscono quindi un vocabolario comune che facilita la comunicazione tra progettisti
2

Design pattern nella libreria Java


I pattern sono utilizzati pervasivamente dalle classi standard di Java, e sono alla base della progettaziione orientata agli oggetti

Esempi:
Abstract, Iterator, Factory, Singleton, Flyweight, State, Strategy, Proxy, Adaptor e Decorator

Esempio: Singleton
A volte una classe contiene per definizione un solo oggetto e.g., una tabella in cui ogni elemento individuato univocamente da un suo campo identificatore (se ci fossero piu` tabelle non si avrebbe garanzia di unicit) Altri es.: registro, log, device driver, Usare una variabile globale (dove mettere la tabella, ecc.) non mai una buona idea... Bisogna assicurare che una classe abbia una sola istanza e fornire un punto d'accesso globale a tale istanza. Ci sono varie possibilit, ma il pattern Singleton lo standard Non si pu assicurare che esista un solo esemplare della classe, se viene reso visibile il costruttore: Ogni chiamata del costruttore genera un nuovo oggetto. 4 Come fare a restituire la sola copia dell'oggetto?

Factory Method
Soluzione:
ll costruttore e` protected o private La creazione possibile invocando un metodo pubblico statico, detto factory: restituisce un oggetto di una classe senza essere costruttore di quella classe

La soluzione con una factory generale:


factory method anche il nome di un pattern (fra i pi usati)--ma non questo Questo uso detto simple factory Spesso (ma non in questo caso) il metodo sta in un'altra classe (Factory Class)
5

UML per Singleton

Adapter
Software esistente usa un'interfaccia Altro software esistente ne usa un'altra Come combinarle senza cambiare il software? Molto spesso librerie diverse espongono interfacce diverse per fare la stessa cosa
Es. librerie grafiche. Software scritto per Windows che vienbe portato sotto MacOS o X (ambienti grafici incompatibili tra loro)

Adattare
Si interpone un Adapter con interfaccia esistente che richiama i metodi dell'oggetto da adattare (Adaptee)

I client vedono solo un'Interfaccia Target (o una classe astratta) Una classe concreta che implementa l'interfaccia 'si occupa di adattare i metodi verso gli Adaptee Risultato: non si modifica ne' il Client ne' l'Adaptee

Spiegazione

(Figura da Head First Design Patterns, Freeman et al, O'Reilly, October 2004)

UML

10

Altro esempio: Proxy


Posporre o addirittura evitare listanziazione di oggetti pesanti, se non necessaria Si interpone un oggetto (Proxy) con la stessa interfaccia delloggetto pesante, di cui fa le veci Oggetto pu fare preprocessing (es. compressione dati perche' l'oggetto pesante su un server remoto) A volte oggetto pu rispondere alle richieste direttamente (es. via cache delle richieste precedenti) I client dell'oggetto chiamano i metodi di un subject (tipo statico interfaccia o classe astratta), il cui tipo dinamico il proxy. 11

Class Diagram del Proxy

12

Sequence diagram del Proxy


: Client 1: request( ) 2: preProcess( ) 3: : Proxy : Server

4: request( ) 5: 6: postProcess( ) 7:

Some private processing operations

13

Strategy
Il pattern Strategy fornisce un oggetto che compie unoperazione precisa, richiesta dallesterno
Per esempio, stabilire un ordinamento tra oggetti Strategy individua una famiglia di algoritmi, da incapsulare in classi dedicate

Strategy e' un esempio di delegation Un comportamento viene delegato a un'altra classe Un esempio di questo pattern nellinterfaccia Comparator di JDK 1.4

14

UML

15

Esempio di Strategy: ordinamento di oggetti qualunque


Ordinare un contenitore di oggetti (p.es. un array) La procedura di ordinamento sempre la stessa per tutti i tipi di oggetti possibili vorremmo quindi fare un unico metodo per tutti i tipi.
public static void sort(Object []s

ma serve un modo per confrontare gli elementi in s! Object non ha un metodo per il confronto e quindi occorre definirlo da qualche altra parte Idea: aggiungo come argomento al metodo un oggettino incaricato del confronto. Per potere rendere il metodo sort applicabile a ogni tipo, loggetto sar di tipo interfaccia. Quindi:
definisco l'interfaccia Comparator (esiste peraltro in java.util), che definisce sintatticamente il confronto di due oggetti fornisco una implementazione di Comparator per il tipo che voglio ordinare (es. IntegerComparator) Passo anche un Comparator quando chiamo la procedura per confrontare gli elementi
16

Strategy: Interface Comparator


interface Comparator { //OVERVIEW: immutabile public int compare (Object o1, Object o2) throws ClassCastException, NullPointerException; /*@ensures (* se o1 e o2 non sono di tipi confrontabili @ lancia ClassCastException @ altrimenti: o1<o2 ret 1 @ o1==o2 ret 0 @ o1>o2 ret 1 } NB: interfaccia non supertipo dei tipi i cui elementi vanno 17 comparati!

metodo statico sort


Argomento aggiuntivo: un oggetto di tipo Comparator (uno solo per tutti gli elementi!). Esempio da java.util.Arrays:
public static void sort (Object[] a, Comparator c) { if (c.compare(a.[i], a.[j]) } Es. di uso: public class AlphabeticComparator implements Comparator{ public int compare(Object o1, Object o2) { String s1 = (String)o1; String s2 = (String)o2; return s1.toLowerCase().compareTo( s2.toLowerCase()); } } ...String[] s = new String[30]; ... Java.util.Arrays.sort(s, new AlphabeticComparator()); ...
18

Ulteriori casi di Strategy


Client potrebbe essere classe astratta, con un campo = oggetto di tipo Strategy
es. protected Strategy strategy;

La Strategy giusta scelta dal costruttore di ciascun erede concreto del client
public ClientConcreto1() {strategy = new ConcreteStrategyA();

... la Strategy potrebbe anche cambiare a run-time!

Molto usato quando si ha una famiglia di comportamenti, che sono usati all'interno di una gerarchia
Molti elementi della gerarchia usano lo stesso comportamento
19

Es: Personaggi di adventure game

Ci sono vari tipi di armi, a ciascuna delle quali corrisponde un diverso modo di combattere. L'arma pu essere cambiata con setWeapon();

useWeapon();
20

Soluzione: WeaponBehavior con metodo useWeapon()

(Figura da Head First Design Patterns, Freeman et al, O'Reilly, October 2004)

21

Classificazione dei pattern


Pattern creazionali
Riguardano il processo di creazione di oggetti Es. Singleton

Pattern strutturali
Hanno a che fare con la composizione di classi ed oggetti Es. Proxy

Pattern comportamentali
Si occupano di come oggetti interagiscono reciprocamente e distribuiscono fra loro le responsabilit Es. Strategy

22

Catalogo

Riferimenti

DesignPatternElementi

perilriusodisoftwareadoggetti
Autori:Gamma,Helm,Johnson,Vlissides.

Decorator
Un adapter che fornisce funzionalit aggiuntive a un Component: Decorator Il Decorator Pattern aggiunge dinamincamente nuove capacit a un oggetto (il Component) La libreria di classi di Java (Stream, RMI, interfaccia grafica) utilizza pesantemente Adaptor, Proxy e Decorator Il Decorator dello stesso tipo del Component: si pu sostituire dove ci si aspetta il Component

Il Decorator contiene un Component


Posso applicare pi Decorator allo stesso oggetto! Ma con cautela...
25

Decorator

26

Uso del Decorator


I decoratori forniscono un'alternativa flessibile alle sottoclassi per estendere le funzionalit di una classe A differenza della definizione di sottoclassi, consente di estendere anche a run time funzionalit di un oggetto esistente Es. package java.io

27

Es. tratto da java.io


Abstract stream Abstract decorator Concrete streams Concrete decorators

28

Flyweight pattern
Quando molti oggetti identici (e immutabili) vengono utilizzati contemporaneamente, utile costruire solo un oggetto per ogni classe di equivalenza di oggetti identici
gli oggetti condivisi vengono chiamati flyweight (pesi mosca) perch spesso sono molto piccoli

Questo pattern va ovviamente usato solo se il numero di oggetti condivisi molto elevato Gli oggetti flyweight devono essere immutabili per evitare problemi di condivisione/aliasing

29

Flyweight: implementazione del pattern


Occorre una tabella per memorizzare gli oggetti flyweight quando vengono creati Se necessario, occorre rimuovere gli oggetti dalla tabella quando non sono piu` utilizzati Efficiente usare questo pattern se c un alto grado di condivisione degli oggetti (immutabili)
si risparmia memoria non si perde tempo a inizializzare oggetti duplicati si pu usare == per il confronto al posto di equals.

Non si possono usare i costruttori


un costruttore costruisce sempre una nuova istanza! naturale usare una factory class per creare gli oggetti; La classe contiene la tabella e la factory
la factory deve controllare se loggetto richiesto esiste gia`nella tabella prima di crearlo; se non esiste, chiama un costruttore (privato!), altrimenti restituisce un reference alloggetto esistente.
30

UML per Flyweight

31

Esempio: uso di pattern flyweight


Classe Word per rappresentare parole immutabili in applicazioni di elaborazione testi
package WordProcessor; public class Word { //OVERVIEW: Words are strings that provide //methods to produce them in various forms; words are immutable; for // each unique string there is at most one word protected Word(String s) //constructor of the unique word for string s // other word methods } package WordProcessor; public static class WordFactory { private static Hashtable t; //maps strings to words public static makeWord(String s) //factory: returns the word for string s //if s is in t return t[s]; else return new Word(S) }
32