Modulo 18 Design Patterns Behavioral Categoria Behavioral z Questi pattern sono dedicati all'assegnamento di responsabilità tra gli oggetti e alla creazione di algoritmi. z Una caratteristica comune in questi pattern è il supporto per seguire le comunicazioni che avvengono tra le classi. z l'utilizzo di questi pattern permette di dedicarsi principalmente alle connessioni tra oggetti lasciando in disparte la gestione dei flussi di controllo. Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 2 1 I Design Pattern Behavioral Design Patterns Chain of Responsability Descrizione Evita l’accoppiamento di chi manda una richiesta con chi la riceve dando a più oggetti la possibilità di gestire la richiesta. Command Incapsula una richiesta in un oggetto in modo da poter eseguire operazioni che non si potrebbero eseguire. Interpreter Dato un linguaggio, definisce una rappresentazione per la sua grammatica ed un interprete per le frasi del linguaggio. Iterator Fornisce una modalità di accesso agli elementi di un oggetto aggregato in modo sequenziale senza esporre la rappresentazione sottostante Mediator Definisce un oggetto che incapsula il modo in cui un insieme di oggetti interagisce in modo da permettere la loro indipendenza Memento Cattura e porta all'esterno lo stato interno di un oggetto senza violare l'incapsulazione in modo da ripristinare il suo stato più tardi Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 3 I Design Pattern Behavioral (2) Design Patterns Observer State Strategy Template method Visitor Descrizione Definisce una dipendenza 1:N tra oggetti in modo che se uno cambia stato gli altri siano aggiornati automaticamente Permette ad un oggetto di cambiare il proprio comportamento a seconda del suo stato interno, come se cambiasse classe di appartenenza Definisce una famiglia di algoritmi, li incapsula ognuno e li rende intercambiabili in modo da cambiare in modo indipendente dagli utilizzatori Definisce lo scheletro di un algoritmo in un'operazione lasciando definire alcuni passi alle sottoclassi Rappresenta un'operazione da fare sugli elementi della struttura di un oggetto. Lascia definire nuove operazioni senza cambiare classe degli elementi Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 4 2 Chain of Responsability z Scopo: z Evitare l’accoppiamento tra l’oggetto che invia una richiesta e l’oggetto che la riceve, offrendo a più oggetti la possibilità di gestire la richiesta. z Formare una catena di oggetti riceventi e trasmettere la richiesta lungo la catena, fino a quando un oggetto non la gestisce. Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 5 Chain of Responsability (Struttura) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 6 3 Chain of Responsability (Diagramma delle istanze) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 7 Chain of Responsability (Esempio)(1) z Problema: z Gestire l’aiuto contestuale di un’applicazione, in modo che se l’aiuto specifico per un controllo non esiste, si faccia riferimento ad un aiuto sempre più generale, fino ad arrivare all’aiuto relativo all’intera applicazione Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 8 4 Chain of Responsability (Esempio)(2) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 9 Chain of Responsability (Esempio)(3) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 10 5 Chain of Responsability (Esempio)(4) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 11 Chain of Responsability: Esercizio z Una azienda commerciale deve gestire le richieste di credito dei clienti (customers). Internamente l’azienda si organizza in diversi livelli di responsabilità. z Al livello più basso (vendor) viene consentito l’approvazione di richieste fino a un importo determinato. z Le richieste che superano questo importo vanno gestite da un livello superiore (sales manager), il quale ha un altro importo massimo da gestire. z Richieste che vanno oltre quest’ultimo importo, vanno gestire da un livello più alto ancora (client account manager). Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 12 6 Chain of Responsability: Esercizio z Diagramma UML: Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 13 Chain of Responsability: Esercizio z Partecipanti: z Handler: classe CreditRequestHandler. z z z ConcreteHandler: classi Vendor, SalesManager e ClientAccountManager. z z z Specifica una interfaccia per la gestione delle richieste. In modo opzionale, implementa un riferimento a un oggetto successore. Gestiscono le richieste che corrispondono alla propria responsabilità. Accedono ad un successore (se è possibile), nel caso in cui la ichiesta non corrisponda alla propria gestione. Client: classe Customer. z Inoltra una richiesta a un ConcreteHandler della catena. Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 14 7 Chain of Responsability: Implementazione in Java (1) z Nodo della catena… (senza logica di controllo) public abstract class CreditRequestHandler { private CreditRequestHandler successor; public void setSuperiorRequestHandler( CreditRequestHandler theSuperior ) { successor = theSuperior; } public void creditRequest( int amount ) throws CreditRequestHandlerException { forwardCreditRequest( amount ); } protected void forwardCreditRequest( int amount ) throws CreditRequestHandlerException { if( successor != null ) successor.creditRequest( amount ); else throw new CreditRequestHandlerException(); Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 } } 15 Chain of Responsability: Implementazione in Java (2) z Una delle classi derivate … (con la logica di controllo) public class SalesManager extends CreditRequestHandler { public void creditRequest( int amount ) throws CreditRequestHandlerException { if( amount <= 1000 ) if( Math.random() < .3 ) System.out.println( "Accepted by Sales Manager." ); else System.out.println( "Not accepted by Sales Manager." ); else forwardCreditRequest( amount ); } } Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 16 8 Chain of Responsability: Implementazione in Java (3) Esempio di utilizzo z public class ChainOfResponsibilityExample { public static void main(String[] arg) throws CreditRequestHandlerException { ClientAccountManager clientAccountMgr = new ClientAccountManager(); SalesManager salesMgr = new SalesManager(); Vendor vendor = new Vendor(); vendor.setSuperiorRequestHandler( salesMgr ); salesMgr.setSuperiorRequestHandler( clientAccountMgr ); Customer customer = new Customer(); int i=500; while( i <= 2500 ) { System.out.println( "Credit request for : $"+ i ); customer.requestCredit( vendor, i ); i += 500; } } Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 } 17 Chain of Responsability: Commenti z La chain of responsability è un meccanismo debole di propagazione dei messaggi: z z Approccio cooperativo Nessuno può assicurare che un handler rilasci il controllo correttamente ad un handler successivo z Win16 e Win32 soffrivano di questo problema nel controllo dei processi z Meccanismo snello se implementato correttamente z In java, un approccio alterativo è rappresentato dal meccanismo di gestione delle eccezioni Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 18 9 Command z Scopo: z Incapsulare una richiesta in un oggetto, quindi lasciare al programmatore la possibilità di parametrizzare il codice chiamante per richieste di diverso tipo, e operazioni di tipo undoable Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 19 Command (Struttura) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 20 10 Command (Esempio) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 21 Command (Esempio) (2) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 22 11 Command (Esempio) (3) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 23 Command (Esempio) (4) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 24 12 Command (Partecipanti) z Command z z ConcreteCommand (PasteCommand, OpenCommand) z z z Crea un oggetto ConcreteCommand e imposta il suo receiver. Invoker (MenuItem) z z Definisce il collegamento tra un oggetto receiver e un’azione Implementa Execute invocando le corrispondenti operazioni di Receiver. Client (Application) z z dichiara un’interfaccia per eseguire un’operazione Richiede all’oggeto Command di evadere la richiesta Receiver (Document, Application) z Responsabile dell’esecuzione dell’operazione associata a seguito della richiesta Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 25 Command: Esercizio (1) z Un telecomando universale consente di gestire diversi tipi di elettrodomestici (TV di diversi modelli e marche, Hi-Fi, ecc.). z Durante la fase di progettazione del telecomando si riesce a definire il numero di tasti e la etichetta di ogni singolo tasto, ma non le operazione concrete da eseguire (vale dire, il segnale particolare da spedire all’elettrodomestico). z Si spera che queste operazioni vengano aggiunte, ulteriormente, al momento di configurare il telecomando (ad esempio, l’utente potrebbe scaricare da internet le classi che li servono per i propri elettrodomestici). z Il problema consiste nella progettazione di una classe (telecomando), in grado di inoltrare richieste verso oggetti che saranno noti solo in fasi successive di sviluppo. Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 26 13 Command: Applicazione del pattern Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 27 Coomand: Implementazione in Java (1) z Si creano le interfacce delle classi che devono implementare i prodotti di tutte le famiglie. public interface Media { } public interface Player { public void accept( Media med ); public void play( ); } public interface Recorder { public void accept( Media med ); public void record( String sound ); } Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 28 14 Command: Implementazione in Java (2) z Implementazione di un Command class TVPowerCommand implements Command { private TV theTV; public TVPowerCommand ( TV someTV ) { theTV = someTV ; } public void execute() { theTV.power(); } } Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 29 Command: Implementazione in Java (3) z Implementazione del receiver public class TV { public static final int ON = 1; public static final int OFF = 0; private int power = OFF; private int volume = 0; private int channel = 2; public void power() { if( power == OFF ) { power = ON; System.out.println( "The TV is ON." ); } else { power = OFF; System.out.println( "The TV is OFF." ); } } ... Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 } 30 15 Command e Functor z I command assomigliano ai functor (oggetti funzione) z Tuttavia: z z Nei functor l’attenzione è posta nella parametrizzazione dell’operazione I command sono principalmente oggetti di collegamento tra l’invoker e il receiver Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 31 Iterator z Scopo: z Fornire un modo per accedere agli elementi di un oggetto aggregato in sequenza senza preoccuparsi della rappresentazione sottostante Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 32 16 Iterator (Struttura) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 33 Iterator (Esempio) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 34 17 Iterator: Esercizio z Il percorso di un viaggiatore è rappresentato come una collezione ordinata di oggetti, dove ogni oggetto rappresenta un luogo visitato. z La collezione può essere implementata in base a array, una linked list o qualunque altra struttura. z Una applicazione sarebbe interessata in poter accedere agli elementi di questa collezione in una sequenza particolare, ma senza dover interagire direttamente con il tipo di struttura interna. Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 35 Iterator in Java z Le collection in Java hanno implementano il pattern Iterator a partire dalla introduzione nella versione 1.3 Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 36 18 Iterator: Applicazione del pattern Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 37 Iterator: Implementazione in Java (1) import java.util.LinkedList; import java.util.ListIterator; public class IteratorExample { public static void main( String[] arg ) { LinkedList tour = new LinkedList(); tour.add( "Santiago" ); tour.add( "Buenos Aires" ); tour.add( "Atlanta" ); tour.add( "New York" ); tour.add( "Madrid" ); ListIterator travel = tour.listIterator(); System.out.println( "Percorso andata" ); while( travel.hasNext() ) System.out.println( ((String) travel.next()) ); System.out.println( "Percorso ritorno" ); while( travel.hasPrevious() ) System.out.println( ((String) travel.previous()) ); Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 } 38 } 19 Observer z Scopo: z Definire una associazione uno-a-molti tra oggetti, in modo che quando un oggetto cambia stato, tutte le sue associazioni ne vengano notificate e aggiornate automaticamente. Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 39 Observer (Struttura) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 40 20 Observer (Interazione tra gli oggetti) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 41 Observer (Esempio) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 42 21 Observer: Esercizio z Ad un oggetto (Subject) vengono comunicati diversi numeri. z Questo oggetto decide in modo casuale di cambiare il suo stato interno, memorizzando il numero ad esso proposto. z Altri due oggetti incaricati del monitoraggio dell’oggetto descritto (un Watcher e un Psychologist), devono avere notizie di ogni suo singolo cambio di stato, per eseguire i propri processi di analisi. Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 43 Observer: Esercizio z Diagramma UML: Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 44 22 Observer: Implementazione in Java (1) z Implementiamo il Subject import java.util.Observer; import java.util.Observable; public class ObservedSubject extends Observable { private int value = 0; public void receiveValue( int newNumber ) { if (Math.random() < .5) { System.out.println( "Subject : I like it, I’ve changed my internal value." ); value = newNumber; this.setChanged(); } else System.out.println( "Subject : I not interested in the number."); this.notifyObservers(); } Luigi Troiano di Produzione del{Software: Modulo 18 public int- Tecnologie returnValue() return value; } 45 } Observer: Implementazione in Java (2) z Implementazione di un Observer import java.util.Observer; import java.util.Observable; public class Psychologist implements Observer { private int countLower, countHigher = 0; public void update(Observable obs, Object arg) { int value = ((ObservedSubject) obs ).returnValue() ; if( value <= 5 ) countLower++; else countHigher++; } public String opinion() { float media; if( (countLower + countHigher ) == 0 ) return( "The Subject doesn’t like changes."); else if( countLower > countHigher ) return( "The Subject likes little numbers."); else if ( countLower < countHigher ) return( "The Subject likes big numbers."); else return( "The Subject likes little numbers and big numbers."); Luigi}Troiano - Tecnologie di Produzione del Software: Modulo 18 } 46 23 Observer: Implementazione in Java (3) Esempio di utilizzo z public class ObserverExample { public static void main (String[] args) { ObservedSubject s = new ObservedSubject() ; Watcher w = new Watcher(); Psychologist p = new Psychologist(); s.addObserver( w ); s.addObserver( p ); for(int i=1;i<=10;i++){ System.out.println( "Main : Do you like the number " + i +"?" ); s.receiveValue( i ); } System.out.println( "The Subject has changed " + w.observedChanges() + " times the internal value."); System.out.println("The Psychologist opinion is:" + p.opinion() ); } } Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 47 Observer in Java z Java estende il modello originalmente proposto dai GoF, in modo di poter associare un singolo Observer a più Subject contemporaneamente. z Questo è consentito dal fatto che il metodo di update dell’Observer riceve come parametro un riferimento al Subject che fa la notifica, consentendo al primo di conoscere quale di tutti i Subject la ha originato. Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 48 24 Strategy z Scopo: z Definire una famiglia di algoritmi, incapsulandoli ognuno, e rendendoli intercambiabili. Strategy consente di variare l’algoritmo indipendentemente dal client. Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 49 Strategy (Struttura) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 50 25 Strategy (Esempio) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 51 Strategy: Esercizio z z z z z La progettazione di una applicazione che offre delle funzionalità matematiche, considera la gestione di una apposita classe (MyArray) per la rappresentazione di vettori di numeri. Tra i metodi di questa classe si ha definito uno che esegue la propria stampa. Questo metodo potrebbe stampare il vettore nel seguente modo (chiamato, ad es. MathFormat):. { 12, -7, 3, … } oppure di questo altro modo (chiamato, ad. es. SandardFormat): Arr[0]=12 Arr[1]=-7 Arr[2]=3 … E’ anche valido pensare che questi formati potrebbero posteriormente essere sostituiti da altri. Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 52 26 Strategy: Applicazione del pattern Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 53 Strategy: Implementazione in Java (1) z La classe astratta ArrayDisplayFormat public interface ArrayDisplayFormat { public void printData( int[] arr ); } Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 54 27 Strategy: Implementazione in Java (2) z Implementazione di una strategy public class StandardFormat implements ArrayDisplayFormat { public void printData( int[] arr ) { System.out.print( "{ " ); for(int i=0; i < arr.length-1 ; i++ ) System.out.print( arr[i] + ", " ); System.out.println( arr[arr.length-1] + " }" ); } } Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 55 Strategy: Implementazione in Java (3) z Implementazione del context public class MyArray { private int[] array; private int size; ArrayDisplayFormat format; public MyArray( int size ) { array = new int[ size ]; } public void setValue( int pos, int value ) {array[pos] = value; } public int getValue( int pos ) { return array[pos]; } public int getLength( int pos ) { return array.length; } public void setDisplayFormat( ArrayDisplayFormat adf ) { format = adf; } public void display() { format.printData( array ); Luigi}Troiano - Tecnologie di Produzione del Software: Modulo 18 } 56 28 Sommario z I Behavioral Design Patterns sono un insieme di 11 patterns proposti nel catalogo GOF z Essi affrontano il problema di come parametrizzare l’interazione tra oggetti z I pattern considerati sono stati: z Chain of Responsability z Command z Iterator z Observer z Strategy Luigi Troiano - Tecnologie di Produzione del Software: Modulo 18 57 29