1 Introduzione ai design pattern. 2 Cosa sono i design pattern I problemi incontrati nello sviluppare grossi progetti software sono spesso ricorrenti.

Slides:



Advertisements
Presentazioni simili
Programmazione ad oggetti
Advertisements

Recupero debito quarto anno Primo incontro
Recupero debito quarto anno Secondo incontro
Informatica Recupero debito quarto anno Terzo incontro.
Informatica 2 Lezione 4 Corso di laurea in matematica Informatica 2 Dott. Ing. Leonardo Vito Corso di laurea matematica indirizzo matematica per le applicazioni.
1 Astrazioni sui dati : Specifica ed Implementazione di Tipi di Dato Astratti in Java.
1 Semantica Operazionale di un frammento di Java: lo stato.
Classi ed Oggetti in Java (Cenni). Richiami Ruolo delle Classi in Java Oggetti.
Liste di Interi Esercitazione. Liste Concatenate Tipo di dato utile per memorizzare sequenze di elementi di dimensioni variabile Definizione tipicamente.
MultiSet, Liste Ordinate
Le gerarchie di tipi.
Esercitazione Frame. Argomento Realizzazione di un tipo di dato astratto Usare le eccezioni per segnalare situazioni particolari Invariante e funzione.
LIP: 19 Aprile Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.
Metodologie di Programmazione = decomposizione basata su astrazioni
1 Le gerarchie di tipi: implementazioni multiple e principio di sostituzione.
PolyFun. Dare implementazione,funzione di astrazione, invarianti della rappresentazione. Provare che i metodi apply e bind preservano gli invarianti.
1 Astrazioni sui dati : Ragionare sui Tipi di Dato Astratti.
Liste Ordinate 3 Maggio Ultima Lezione Abbiamo visto i tipi di dato astratti IntList e StringList Realizzano liste di interi e di stringhe Realizzati.
LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.
Fondamenti di Informatica
1 Programmazione ad oggetti in Java E.Mumolo, DEEI
Astrazioni sul controllo Iteratori. 2 Nuove iterazioni Definendo un nuovo tipo come collezione di oggetti (p. es., set) si vorrebbe disporre anche di.
Specifiche senza JML: uso delle asserzioni. 2 Asserzioni in Java Dal jdk 1.4 (da Febbraio 2002) cè meccanismo per gestire asserzioni Asserzione: espressione.
Algoritmi e Strutture Dati IV. Heap e Code di Priorità
Overriding.
Approfondimento delle classi
1 Le gerarchie di tipi. 2 Supertipi e sottotipi 4 un supertipo –class –interface 4 può avere più sottotipi –un sottotipo extends il supertipo ( class.
Le classi Definizione di classe Attributi e metodi di una classe Costruttori e distruttori Private e public Funzioni friend Il puntatore this.
1 Programmazione = decomposizione basata su astrazioni (con riferimento a Java)
1 Astrazioni sui dati : Ragionare sui Tipi di Dato Astratti dispense prof. G. Levi.
Enumerazioni e Classi 1. Enumerazioni Permettono di definire nuovi tipi che consistono in un insieme di valori costanti (ognuno con un nome) – Migliorano.
1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.
Fopndamenti di programmazione. 2 La classe String Una stringa è una sequenza di caratteri La classe String è utilizzata per memorizzare caratteri La classe.
Corso JAVA Lezione n° 11 Istituto Statale di Istruzione Superiore “F. Enriques”
1 cin>>c8 s.r.l A.A Generalità Uno dei concetti largamente adottati negli ultimi anni dai professionisti del software in fase di sviluppo.
1 Un esempio con iteratore: le liste ordinate di interi.
Heap concetti ed applicazioni. maggio 2002ASD - Heap2 heap heap = catasta condizione di heap 1.albero binario perfettamente bilanciato 2.tutte le foglie.
Ereditarieta’. Contenuti Introduciamo un meccanismo fondamentale di Java: l’ereditarieta’ Permette di estendere classi gia’ definite (ovvero di definire.
Esercitazione su Vector. Permette di definire collezioni di dati generiche, che sono in grado di memorizzare elementi di ogni sottotipo di Object Definito.
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 7 Tipi di dato e strutture dati Specifica e realizzazione di strutture informative come classi.
Astrazione di dati Dati Astratti: cosa e perchè Dati Astratti: due meccanismi differenti Dati Astratti: due meccanismi differenti Astrazione e incapsulamento.
1 Eccezioni in Java. 2 Ricordiamo che 4 una procedura può terminare –normalmente, ritornando un risultato –in modo eccezionale ci possono essere diverse.
L.Lista, V. Innocente Design P atterns Luca Lista, Vincenzo Innocente.
Liste di Interi Esercitazione. Una variante Liste concatenate di Integers Non modificabile Costruttori per creare la lista vuota o un nodo Metodi d’istanza.
Specifiche. Scopo e significato delle specifiche (1) Lo scopo di una specifica è di definire il comportamento di un ’ astrazione. Gli utenti si baseranno.
Liste di Interi Esercitazione. IntList Lista di interi Problema tipico: memorizzare una sequenza di valori [6,0,9,3….9] Vediamo un tipo di dato utile.
Liste Concatenate 11 Aprile E’ una delle strutture dati fondamentali in tutti i linguaggi di programmazione di alto livello Una Lista Concatenata.
Liste di Interi Esercitazione. IntList Lista di interi Una lista è una disposizione ordinata di elementi ( non in modo crescente-descrescente, ma per.
1 Gerarchie e polimorfismo: liste. 2 Generalizzare le liste di interi  List 4 lista di oggetti –non modificabile 4 vorremo poi definire un sottotipo.
1 Astrazione sul controllo: gli iteratori. 2 Gli iteratori 4 perché vogliamo iterarare “in modo astratto” 4 iteratori e generatori in Java –specifica.
1 Astrazioni sui dati : Ragionare sui Tipi di Dato Astratti.
Esercitazione del 7 marzo 2008 Ereditarieta’. Esercizio: soluzione Implementare la seguente specifica che definisce un tipo di dato Libro.
LIP: 2 Maggio 2008 Classi Astratte. Cos’e’ una Classe Astratta una classe astratta e’ un particolare tipo di classe permette di fornire una implementazione.
1 Astrazione sul controllo: gli iteratori. 2 Perché vogliamo iterare “in modo astratto” 4 problema: iterare su tipi di dato arbitrari  esempio: procedura.
Sommario Oggetti immutabili e non Tipi Primitivi: String, Arrays.
Progettare una classe 21 Febbraio La classe BankAccount Vogliamo realizzare una classe i cui oggetti sono dei semplici conti bancari. * Identifichiamo.
1 Astrazioni sui dati : Specifica ed Implementazione di Tipi di Dato Astratti in Java.
1 Astrazioni sui dati : Specifica ed Implementazione di Tipi di Dato Astratti in Java.
LIP: 11 Maggio 2007 Classi Astratte. Cos’e’ una Classe Astratta una classe astratta e’ un particolare tipo di classe permette di fornire una implementazione.
Esercitazione del 9 marzo 2007 Ereditarieta’. Richiami Definire sottoclassi (ereditarieta’) Overriding Specificatori di accesso (private, protected) Principio.
Liste Concatenate 28 Marzo Avviso Martedi’ 4 Aprile: Verifica di LIP Per iscriversi (obbligatorio) inviare un e- mail entro venerdi’ 31 Marzo a.
1 Un esempio con iteratore: le liste ordinate di interi.
LIP: 4 Maggio 2007 Interfacce. Cos’e’ una Interfaccia una interfaccia e’ un particolare tipo di classe contiene solo la specifica non ha implementazione.
LIP: 15 Marzo 2005 Vettori di interi. Esercizio proposto Definire una classe VectorInt i cui oggetti sono vettori omogenei di interi ordinati in modo.
LIP: 18 Aprile 2008 Interfacce. Rappresentazione Lista val next vuota Lista vuota: any true Lista non vuota: any true 154 false 24 false.
Corso di Algoritmi e Strutture Dati con Laboratorio Richiami di Java – parte II.
30/10/01Array 1  Un array e’ una struttura dati che contiene piu’ valori del medesimo tipo.  La lunghezza di un array e’ stabilita quando l’array viene.
Introduzione all’Ereditarietà Pietro Palladino. Richiami UML Classe: descrizione di un insieme di oggetti software con caratteristiche simili Definisce.
Due slides sui Design Patterns Luciano Pandola INFN-LNGS Corso INFN su C++, ROOT e Geant4.
Introduzione alle Classi e agli Oggetti in Java 1.
Transcript della presentazione:

1 Introduzione ai design pattern

2 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

3 Design pattern nella libreria Java I pattern sono utilizzati pervasivamente dalle classi standard di Java, e sono alla base della progettazione orientata agli oggetti –Es. Iterator: fornisce un modo efficiente e uniforme per accedere a elementi di collezioni Altri esempi presentati in queste slide: –Abstract Factory, Singleton, Flyweight, State, Strategy, Proxy, Adaptor e Decorator

4 Abstract Pattern Costruire implementazioni multiple di una stessa classe Es. Poly densi e sparsi –DensePoly: una implementazione di Poly adatta al caso in cui ci sono pochi coefficienti nulli (ad es. quella vista per i Poly con un array per tutti i coefficienti); –SparsePoly: una diversa implementazione, efficiente quando molti coefficienti sono nulli (es. lista a puntatori, in cui ogni nodo memorizza il coeff. e il grado di ogni termine !=0). Poi però se Dense e Sparse sono tipi distinti dovremmo definire codice diverso per ogni polinomio: public static void DensePoly derivata (DensePoly p) … public static void SparsePoly derivata (SparsePoly p) … ma differenza fra Dense e Sparse è solo implementativa

5 Poly Astratta e impl. multiple Soluzione: definire una classe Poly e definire DensePoly e SparsePoly come sue estensioni (pure) Utilizzatore di Poly vede solo i metodi definiti in Poly. ensures (* \result == derivata di p *); public static Poly derivata(Poly p) Non importa se a runtime p sarà un DensePoly o uno SparsePoly. Poly non contiene un rep (perche non vi molto in comune fra le due implementazioni): saranno sottoclassi a stabilire modalità di memorizzazione Quindi Poly deve diventare astratta: non è possibile fare add, ecc. senza il rep. Gerarchia di tipi può essere utilizzata per fornire più implementazioni dello stesso tipo Il tipo da implementare è di solito descritto con interfaccia (se nessuna operazione è implementabile) o classe astratta (se alcune operazioni sono implementabili) Poly DensePoly SparsePoly

6 Creazione di oggetti? Il codice di un programma orientato agli oggetti non dipende dalla precisa classe cui appartiene un certo oggetto. I programmi richiedono a un oggetto solo il rispetto del contratto corrispondente alla sua specifica (il suo tipo) –Limitare le dipendenze dalle classi è desiderabile perché permette di sostituire unimplementazione con unaltra. es si può usare Poly e poi se si passa una DensePoly o una SparsePoly tutto funziona lo stesso Eccezione: le chiamate ai costruttori : il codice utente che chiama il costruttore di una determinata classe rimane vincolato a quella classe Ci piacerebbe potere lasciare alla classe Poly stessa la scelta se il tipo da costruire e' uno SparsePoly o un DensePoly!

7 Factory Method La soluzione è nascondere la creazione in un metodo detto factory: restituisce un oggetto di una classe senza essere costruttore di quella classe –Esempio: il metodo che restituisce loggetto iteratore associato a un contenitore (nella nomenclatura Liskov, oggetti generatori): e` un esemplare di una classe che implementa linterfaccia Iterator, ma il metodo non e` un costruttore; In Java le chiamate ai costruttori non sono personalizzabili. Una factory può invece scegliere la strategia di allocazione.

8 Factory (2) Il metodo può creare oggetti di classi diverse a seconda dei parametri, ma tutti questi oggetti avranno lo stesso tipo. –Esempio: un polinomio del tipo ax n +b viene implementato da una classe SparsePoly, mentre il polinomio generico è un esemplare di DensePoly. public static Poly createPoly (int[] a) { int degree = -1, numCoeffs = 0; for (int n = 0; n < a.length; n++) if (a[n] != 0){ numCoeffs++; degree = n; } if ((numCoeffs == 2 && a[0] != 0) || numCoeffs == 1) return new SparsePoly (degree, a[degree], a[0]); return new DensePoly (degree, a); }

9 Alternativa: Factory Class A volte e' preferibile che il metodo statico sia in una classe a parte Es. public class FabbricaDiPoly public static Poly createPoly (int[] a) {... } Ad es. puo' essere comodo per aggiungere operazioni che influenzano che cosa si vuole fabbricare o per non consentire la costruzione di oggetti di tipo Poly a chi vede solo la classe Poly

10 Abstract Factory La soluzione non è ottimale dal punto di vista dell'estendibilita': cosa succede se aggiungiamo una classe PolyMezzoDenso che implementa un Poly per i casi intermedi ne' densi ne' sparsi? Dobbiamo modificare il metodo factory, violando principio Open/Closed. Allora si può usare Abstract Factory –La Factory Class è astratta: il metodo factory e' astratto –C'e' un'erede concreta della Factory per ogni classe concreta dell'implementazione, che implementa il metodo giusto (FactoryDensePoly, FactorySparsePoly) –Estendendo la classe Poly con PolyMezzoDenso ci basta aggiungere una FactoryPolyMezzoDenso

11 Abstract Factory descritto in UML

12 Pattern per Ottimizzazioni comuni Alcuni pattern forniscono trucchi semplici e funzionali per velocizzare un programma o ridurne i requisiti di memoria. A volte lutilizzo di questi pattern non fa parte del progetto vero e proprio del sistema, ma un programmatore competente sa riconoscere le occasioni in cui usarli efficacemente

13 Singleton A volte una classe contiene per definizione un solo oggetto e.g., una tabella, un archivio in cui si assume che ogni elemento sia individuato univocamente dal suo identificatore (quindi se ci fossero piu` tabelle non si avrebbe questa garanzia di unicità) Usare una normale classe con soli metodi statici non assicura che esista un solo esemplare della classe, se viene reso visibile il costruttore In una classe Singleton il costruttore e` protetto o privato Un metodo statico, o una factory, forniscono laccesso alla sola copia delloggetto

14 Singleton pattern: il tipico codice public class SingletonClass { private static SingletonClass s; //the single instance public static SingletonClass getObject(){ //build the unique object only if it does not exist already if (s == null) s = new SingletonClass(); return s; } private SingletonClass() { … } // the constructor // other methods }

15 Flyweight Quando molti oggetti identici (e immutabili) vengono utilizzati contemporaneamente, e` utile costruire solo un oggetto per ogni classe di equivalenza di oggetti identici –gli oggetti condivisi vengono chiamati flyweight (pesi mosca) perche` spesso sono molto piccoli Questo pattern va ovviamente usato solo se il numero di oggetti condivisi e` molto elevato Gli oggetti flyweight devono essere immutabili per evitare problemi di aliasing

16 Flyweight: implementazione del pattern Occorre una tabella per memorizzare gli oggetti flyweight quando vengono creati Non si possono usare i costruttori –un costruttore costruisce sempre una nuova istanza! –naturale usare una factory class per creare gli oggetti; la factory deve controllare se loggetto richiesto esiste già nella tabella prima di crearlo; se non esiste, chiama un costruttore (privato!), altrimenti restituisce un reference alloggetto esistente. Se necessario, occorre rimuovere gli oggetti dalla tabella quando non sono più utilizzati Efficiente usare questo pattern se cè un alto grado di condivisione degli oggetti –si risparmia memoria –non si perde tempo a inizializzare oggetti duplicati –si può usare == per il confronto al posto di equals.

17 UML per Flyweight

18 Esempio di pattern flyweight classe Word per rappresentare parole immutabili in applicazioni di elaborazione testi 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 private static Hashtable t; //maps strings to words public static makeWord(String s) //factory: returns the word for string s private Word(String s) //constructor of the unique word for string s public String mapWord(Context c) //returns the string corresponding to this in the form // suitable for context c // other word methods }

19 State A volte si vuole usare un'implementazione diversa dello stesso oggetto durante la sua vita –per esempio, una classe vettore può usare una rappresentazione diversa a seconda del numero degli elementi. Se si usa una sola classe il codice degli oggetti mutabili può diventare assai complicato e pieno di condizionali Razionalizzazione della struttura del codice: gli oggetti cambiano configurazione a seconda dello stato in cui si trovano. Il pattern State introduce un ulteriore strato tra il tipo implementato e limplementazione –a un unico tipo si fanno corrispondere piu` classi che lo implementano, e che corrispondono a diversi stati in cui possono trovarsi gli esemplari del tipo –nel corso della vita delloggetto, possono essere utilizzate diverse implementazioni senza che lutente se ne accorga

20 State (2) Implementazione del pattern Si crea uninterfaccia o una classe astratta che rappresenta le parti delloggetto che possono essere sostituite nel corso della vita delloggetto Ciascuna delle possibili rappresentazioni (stati) diventa unimplementazione dellinterfaccia o un erede della classe astratta La classe principale conterrà il codice per scegliere la rappresentazione più adatta e per delegare limplementazione alla sottoclasse piu`appropriata per lo stato delloggetto

21 Esempio di State Classe BoolSet, analogo dellIntset : un insieme di boolean che cambia implementazione a seconda del numero di elementi: si usano due classi SmallBoolSet e BigBoolSet a seconda della cardinalità dellinsieme interface BoolSetState { public boolean get (int n) throws IndexOutOfBoundsException; public BoolSetState set (int n, boolean val) throws IndexOutOfBoundsException; } public class BoolSet { BoolSetState s; public BoolSet () { BoolSetState = new SmallBoolSet (); } public final boolean get (int n) throws IndexOutOfBoundsException { return s.get (n); } public final void set (int n, boolean val) throws IndexOutOfBoundsException { s = s.set (n, val); } }

22 Esempio di State (2) SmallBoolSet usa un singolo long per implementare set i cui elementi sono tutti minori di 64. class SmallBoolSet implements BoolSetState { public static final long MAX_SIZE = 64; long bitset; public boolean get (int n) throws IndexOutOfBoundsException { if (n < 0) throw new ArrayIndexOutOfBoundsException(n); return n < MAX_SIZE && (bitset & (1 << n)) != 0; }

23 Esempio di State (3) Se si imposta a 1 un elemento oltre il 64-esimo, viene creato un BigBoolSet. public BoolSetState set (int n, boolean val) throws IndexOutOfBoundsException { if (n < 0) throw new ArrayIndexOutOfBoundsException(n); if (val) { if (n >= MAX_SIZE) return new BigBoolSet (this).set (n, val); bitset |= (1 << n); } else if (n < MAX_SIZE) bitset &= ~(1 << n); return this; }

24 Esempio di State (4) Per la classe BigBoolSet vediamo solo il metodo che costruisce un BigBoolSet a partire da uno SmallBoolSet: class BigBoolSet implements BoolSetState {... public BigBoolSet (SmallBoolSet s) { for (i = 0; i < s.MAX_SIZE; i++) if (s.get (i)) set (i, true); }... }

25 Procedure come oggetti Java non permette di utilizzare come oggetti le chiamate a un metodo Questo, tuttavia, può essere utile per definire astrazioni altamente generiche ed estendibili (pluggable) Lunico modo di ottenere questo risultato è definire classi o interfacce molto piccole. Ci sono esempi nella libreria di classi di Java –Comparable –Runnable –ActionListener

26 Strategy Il pattern Strategy fornisce un oggetto che compie unoperazione precisa, richiesta dallesterno –Per esempio, stabilire un ordinamento tra oggetti Loperazione è esprimibile con clausole Requires e Ensures Un esempio di questo pattern nellinterfaccia Comparator di JDK 1.4

27 UML

28 Esempio di Strategy: ordinamento di oggetti qualunque Vogliamo 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. Qualcosa come public static void sort(Object []s… (* s è ordinato *) … 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

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

30 metodo 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());...

31 adattare interfacce diverse: Proxy, Adaptor e Decorator Molto spesso librerie diverse espongono interfacce diverse… per fare la stessa cosa –Windows e MacOS sono ambienti grafici incompatibili tra loro Una stessa soluzione si adatta a svariati problemi –si scrivono nuove classi che impongano una stessa interfaccia e uno stesso insieme di precondizioni e postcondizioni Gli esemplari delle nuove classi usano un oggetto interno che contiene la vera implementazione –esempio del motto Every problem in computer science can be solved by adding another level of indirection –loggetto visibile all esterno si chiama oggetto esterno

32 Adaptor La strategia delineata nella slide precedente prende il nome di Adaptor quando linterfaccia delloggetto interno è diversa da quella delloggetto esterno Loggetto esterno e lAdapter, quello interno lAdaptee. –le librerie di classi per linterfaccia grafica, come AWT o Swing, non sono altro che enormi raccolte di oggetti Adapter –in Java, java.io.OutputStreamWriter permette di scrivere caratteri a 16-bit (Unicode) su di un OutputStream che lavora per byte –gli skeleton di RMI mappano su di un protocollo binario i metodi di uninterfaccia Java

33 UML

34 Proxy Quando loggetto interposto espone esattamente la stessa interfaccia delloggetto separato, di cui fa le veci, esso prende il nome di Proxy –java.util.zip.DeflaterOutputStream comprime automaticamente i dati scritti Scopo del Proxy:posporre o addirittura evitare listanziazione di oggetti pesanti, se non necessaria –es. gli stub di RMI sembrano oggetti locali, ma si occupano di serializzare i parametri, inviarli in rete, attendere il risultato, ecc., senza però essere i veri oggetti

35 UML

36 Documentazione UML del pattern Proxy : Client : Proxy : Server 1: request( ) 2: preProcess( ) 3: 4: request( ) 5: 6: postProcess( ) 7: Some private processing operations

37 Decorator Altre volte, invece, loggetto fornisce funzionalità aggiuntive: prende allora il nome di Decorator –java.util.zip.CheckedOutputStream calcola un checksum al volo e possiede un metodo aggiuntivo per restituirlo La libreria di classi di Java (Stream, RMI, interfaccia grafica) utilizza pesantemente Adaptor, Proxy e Decorator

38 Conclusione I pattern forniscono un vocabolario comune tra i progettisti, che facilita la comprensione di un progetto esistente o lo sviluppo di uno nuovo –Abbiamo visto solo un piccolo insieme di pattern: –Factory, Singleton, Flyweight, State, Strategy, Proxy, Adaptor, Decorator I pattern migliorano le prestazioni del codice e/o lo rendono più flessibile Tuttavia, il codice che utilizza i pattern potrebbe risultare più complesso del necessario: occorre quindi valutare e confrontare costi e benefici Svantaggio potenziale: pattern possono rendere la struttura del codice piu`complessa del necessario: di volta in volta bisogna decidere se adottare semplici soluzioni ad hoc o riutilizzare pattern noti –pericolo di overdesign: ricordare i seguenti motti when in doubt, leave it out keep it simple

39 Esercizio: collezione di elementi con somma Si implementi il tipo collezione di elementi con somma (SumSet). Man mano che nuovi elementi vengono aggiunti o tolti dalla collezione viene aggiornata la somma degli elementi Quindi deve esistere l'operazione di somma per gli elementi da inserire Si utilizzi il pattern Strategy, utilizzando un interfaccia Adder che definisce un metodo per la somma

40 Interfaccia Adder public interface Adder{ //OVERVIEW … … … public Object add(Object x, Object y) throws ClassCastException, NullPointerException; public Object sub(Object x, Object y) throws ClassCastException, NullPointerException; public Object zero(); } NB: interfaccia Adder non è supertipo dei tipi i cui elementi vanno sommati Serve, per ogni dato tipo che si voglia inserire nellinsieme a (definire classi per) creare oggetti con metodi per sommare o sottrarre elementi di quel tipo NB: si paga il prezzo della maggiore flessibilità con una maggior quantità di definizioni (un nuovo tipo aggiuntivo per ogni tipo di oggetto da inserire Obiettivo (non perdiamolo di vista!): ottenere classe SumSet polimorfa che non deve essere modificata per inserire nuovi tipi di oggetti

41 Unimplementazione di Adder: PolyAdder public class PolyAdder implements Adder { private Poly z: // il Poly zero public PolyAdder() { z = new Poly();} public Object add (Object x, Object y) throws NullPointerException, ClassCastException { if ( x == null || y == null) throw new NullP….; return ((Poly) x).add((Poly) y); } public Object sub (Object x, Object y) ……………// simile ad add public Object zero () { return z;} } NB: I metodi di PolyAdder (add e sub) sono distinti e diversi dai metodi omonimi di Poly: signature diversa. Per inserire oggetti Integer in SumSet occorrerebbe definire IntegerAdder con add e sub, che Integer non possiede.

42 Classe SumSet (con implementazione parziale) public class SumSet{ //OVERVIEW … … … private Vector els; // contiene gli elementi private Object sum;// contiene la somma private Adder a; //oggetto per sommare e sottrarrre public SumSet (Adder p) throws NullPointerException{ els = new Vector(); a = p; sum= p.zero(); } public void insert (Object x) throws NullP…, ClassCastEx… { … … sum = a.add(sum, x); … } public Object getSum(){return sum;} }

43 Classe SumSet (cont.) Ogni oggetto SumSet definito in termini (corredato) di qualche oggetto Adder Elementi di SumSet tutti omogenei –ma ora tipo degli elementi determinato alla creazione della collezione dalloggetto Adder passato al costruttore: non puo` cambiare Adder a = new PolyAdder(); SumSet s = new SumSet(a); s.insert(new Poly(3, 7)); s.insert(new Poly(4, 8)); Poly p = (Poly) s.sum();// p e` 3x^7+4x^8 NB: loggetto SumSet s può contenere solo oggetti Poly, perché costruito con un PolyAdder. Verifica però fatta a run-time...