SlideShare ist ein Scribd-Unternehmen logo
1 von 48
Lezione 25: Design
    Pattern Comportamentali
         Corso di Ingegneria del Software
       Laurea Magistrale in Ing. Informatica
         Università degli Studi di Salerno



1
Outline


    ✦ Design Pattern Comportamentali
     •   Observer (continuazione)

     •   State

     •   Strategy

     •   Visitor




2
Design Pattern Comportamentali




3
Observer


    ✦ Conseguenze
     •   il Subject è disaccoppiato dagli oggetti che
         dipendono da esso (maggiore riusabilità e
         testabilità)
     •   comunicazione “broadcast”: il Subject non sa
         quanti oggetti dipendono da esso




4
Observer

    ✦ Note
     •   tutti gli Observer sono informati di tutte le
         variazioni dello stato del Subject; in alcuni casi
         questo può essere inefficiente
         ‣   una variante del pattern prevede che i possibili
             cambiamenti di stato siano divisi in categorie (“Topic”), e
             ciascun Observer specifica all’atto della registrazione quali
             sono i topic a cui è interessato




5
Observer

    ✦ Observer vs Chain of Responsibility
     •   i due pattern soddisfano un’esigenza simile, però
         ‣   nella Chain of Responibility si assume che uno solo degli
             handler gestisca effettivamente la richiesta; inoltre c’è una
             priorità tra gli handler: ciascun handler ha la possibilità di
             “filtrare” le richieste che arrivano agli handler successivi
         ‣   gli Observer invece sono tutti allo stesso livello, e
             tipicamente tutti gli observer rispondono in qualche modo
             a ciascun cambiamento (almeno per i Topic a cui sono
             registrati)




6
State

    ✦ Il problema
     •   un oggetto (Context) può trovarsi in più “stati”
         diversi, e il comportamento di alcune operazioni
         deve dipendere dallo stato in cui l’oggetto si trova
     •   si vuole evitare che la dipendenza del
         comportamento dallo stato sia “cablata”
         all’interno dei metodi dell’oggetto perché ciò
         renderebbe difficile cambiare/estendere l’insieme
         degli stati



7
State
    ✦ Esempio del problema
     •   un oggetto che rappresenta un file può essere in
         uno dei seguenti stati:
         ‣   chiuso
         ‣   aperto per operazioni di lettura
         ‣   aperto per operazioni di scrittura
         ‣   aperto per operazioni di lettura e scrittura

     •   le operazioni read e write, a seconda dello stato,
         svolgono la loro funzione oppure lanciano
         un’eccezione


8
State
    ✦ Esempio del problema
     •   in un programma di disegno l’utente può
         selezionare diversi strumenti
         ‣   matita
         ‣   gomma
         ‣   pennello
         ‣   disegno di linee
         ‣   ecc.

     •   il programma deve rispondere agli eventi del
         mouse in modo diverso a seconda dello strumento
         selezionato


9
State
     ✦ Soluzione
      •   lo stato del Context viene trasformato in un
          oggetto, che implementa un’interfaccia State con
          le operazioni che devono essere eseguite
          diversamente per ogni stato
      •   per ogni possibile stato si definisce una
          sottoclasse concreta di State
      •   il Context mantiene un riferimento all’oggetto che
          rappresenta lo stato corrente; per cambiare stato
          viene cambiato questo riferimento
      •   il Context delega allo stato corrente le operazioni
          che sono dipendenti dallo stato
10
State
     ✦ Esempio di struttura




11
State
       ✦ Esempio di soluzione
     import java.awt.*;

     public abstract class Tool {
     	 public void mouseDown(Graphics g, int x, int y) {
     	 	
     	 }
     	
     	 public void dragTo(Graphics g, int x, int y) {
     	 	
     	 }
     	
     	 public void mouseUp(Graphics g, int x, int y) {
     	 	
     	 }
     }

12
State
       ✦ Esempio di soluzione (continua)

     import java.awt.Graphics;

     public class LineTool extends Tool {
     	 private int prevX, prevY;
     	 public void mouseDown(Graphics g, int x, int y) {
     	 	 prevX = x;
     	 	 prevY = y;
     	 }
     	
     	 public void mouseUp(Graphics g, int x, int y) {
     	 	 g.drawLine(prevX, prevY, x, y);
     	 }
     }



13
State
        ✦ Esempio di soluzione (continua)
     import java.awt.Graphics;

     public class FreehandTool extends Tool {
     	 private int prevX, prevY;
     	
     	 public void mouseDown(Graphics g, int x, int y) {
     	 	 prevX = x;
     	 	 prevY = y;
     	 }
     	
     	 public void dragTo(Graphics g, int x, int y) {
     	 	 g.drawLine(prevX, prevY, x, y);
     	 	 prevX = x;
     	 	 prevY = y;
     	 }
     	
     	 public void mouseUp(Graphics g, int x, int y) {
     	 	 g.drawLine(prevX, prevY, x, y);
     	 }
     }

14
State
       ✦ Esempio di soluzione (continua)
     // . . .
     public class Doodle extends Canvas {
     	 private Tool selectedTool;
     	 public Doodle() {
                // . . .
     	 	 addMouseListener(new MouseAdapter() {
     	 	 	 public void mousePressed(MouseEvent evt) {
     	 	 	 	 selectedTool.mouseDown(getGraphics(), evt.getX(), evt.getY());
     	 	 	 }
                     // . . .
     	 	 });
               // . . .
          }
          // . . .
     	 public void setTool(Tool t) {
     	 	 selectedTool=t;
     	 }
          // . . .
     }


15
State

     ✦ Conseguenze
      •   la dipendenza dallo stato non è distribuita nel
          codice di diversi metodi del context, ma è raccolta
          nei metodi delle implementazioni concrete di
          State
      •   è semplice modificare il comportamento di uno
          specifico stato, oppure aggiungere al sistema
          nuovi stati inizialmente non previsti




16
Strategy

     ✦ Il problema
      •   spesso in un determinato contesto è necessario
          effettuare un’operazione (o un insieme di
          operazioni collegate) che può avere
          implementazioni diverse
      •   si vuole rendere il contesto indipendente da una
          particolare implementazione dell’operazione




17
Strategy
     ✦ Esempio del problema
      •   in un algoritmo di ordinamento basato su
          confronti è necessario comparare due oggetti
      •   la comparazione dipende dal tipo di oggetti da
          ordinare, ma anche per un singolo tipo di oggetti
          sono possibili diversi criteri di ordinamento, che
          corrispondono a diverse implementazioni
          dell’operazione di comparazione
      •   si vuole rendere l’algoritmo di ordinamento
          indipendente dal modo in cui viene effettuata la
          comparazione


18
Strategy

     ✦ Soluzione
      •   si definisce una interfaccia Strategy che contiene
          le operazioni di cui si vuole nascondere
          l’implementazione
      •   per ogni implementazione si definisce una
          sottoclasse concreta di Strategy
      •   l’oggetto che rappresenta il contesto (Context)
          riceve un riferimento a un’istanza di una
          sottoclasse concreta di Strategy



19
Strategy
     ✦ Esempio di struttura




20
Strategy
        ✦ Esempio di soluzione
           •    L’interfaccia Comparator nella libreria Java

     package java.util;

     public interface Comparator {
     	 // Confronta due oggetti
        // restituisce un valore <0, =0 o >0
        // a seconda che sia x<y, x=y, x>y
     	 int compare(Object x, Object y);
     	
        // verifica se un altro oggetto è uguale
        // a questo Comparator
     	 boolean equals(Object other);
     }




21
Strategy
        ✦ Esempio di soluzione (continua)
           •   Gli algoritmi di ordinamento nella libreria Java
               ricevono come parametro un Comparator


     public class Collections {
     	 // Ordina una lista
     	 public static List sort(List list, Comparator order) {
            // . . .
     	




22
Strategy

     ✦ Conseguenze
      •   è possibile realizzare in modo semplice famiglie di
          algoritmi simili che differiscono per
          l’implementazione di alcune operazioni
      •   il contesto può cambiare l’implementazione delle
          operazioni anche a run time, scegliendo un
          diverso oggetto Strategy




23
Strategy
     ✦ Template Method vs Strategy
      •   i due pattern risolvono lo stesso problema
      •   differenze:
          ‣   con Template Method non è necessario creare più oggetti
          ‣   con Strategy non c’è un’esplosione combinatoria di
              sottoclassi se il contesto ha più operazioni che devono
              essere incapsulate indipendentemente
          ‣   con Strategy l’implementazione delle operazioni
              incapsulate può essere effettuata a run time
          ‣   una stessa Strategy può essere utilizzata in contesti diversi




24
Strategy
      ✦ Esempio di implementazione
         •   Rivediamo l’esempio delle operazioni di
             accumulazione usando il pattern Strategy invece
             di Template Method
         •   per cominciare, definiamo l’interfaccia Strategy

     public interface AccumulationStrategy {
     	 int initialValue();
     	 int combine(int currentValue, int element);
     }




25
Strategy
       ✦ Esempio di implementazione (continua)
         •   definiamo ora la classe Accumulator
     public class Accumulator {
     	 private AccumulationStrategy strategy;
     	
     	 public Accumulator(AccumulationStrategy strategy) {
     	 	 this.strategy=strategy;
     	 }
     	
     	 public int compute(int a[], int n) {
     	 	 int value=strategy.initialValue();
     	 	 int i;
     	 	 for(i=0; i<n; i++)
     	 	 	 value=strategy.combine(value, a[i]);
     	 	 return value;
     	 }
     }
26
Strategy
       ✦ Esempio di implementazione (continua)
          •   definiamo ora le strategie concrete


     public class SumStrategy implements AccumulationStrategy {
     	 public int initialValue() {
     	 	 return 0;
     	 }
     	
     	 public int combine(int currentValue, int element) {
     	 	 return currentValue+element;
     	 }
     }




27
Strategy
       ✦ Esempio di implementazione (continua)
          •   definiamo ora le strategie concrete


     public class ProductStrategy implements AccumulationStrategy {
     	 public int initialValue() {
     	 	 return 1;
     	 }
     	
     	 public int combine(int currentValue, int element) {
     	 	 return currentValue*element;
     	 }
     }




28
Strategy
        ✦ Esempio di implementazione (continua)
           •   definiamo ora le strategie concrete
     public class CountPositiveStrategy implements AccumulationStrategy
     {
     	 public int initialValue() {
     	 	 return 0;
     	 }
     	
     	 public int combine(int currentValue, int element) {
     	 	 if (element>0)
     	 	 	 return currentValue+1;
     	 	 else
     	 	 	 return currentValue;
     	 }
     }


29
Strategy
        ✦ Esempio di implementazione (continua)
          •   esempio di uso di Accumulator:




     	 	 AccumulationStrategy strategy=new SumStrategy();
     	 	 Accumulator acc=new Accumulator(strategy);
     	 	 int sum=acc.compute(a,n);




30
Strategy
     ✦ State vs Strategy
      •   i due pattern sono molto simili (da un punto di
          vista implementativo sono identici)
      •   la differenza è nella finalità:
          ‣   Strategy serve a parametrizzare un algoritmo, State serve
              a semplificare l’implementazione di un comportamento
              complesso
          ‣   Una Strategy generalmente non cambia durante l’esistenza
              del Context (anche se è possibile farlo); uno State invece
              quasi sempre cambia durante l’esecuzione
          ‣   Di solito il Context conosce tutti i possibili State che sono
              applicabili (e gestisce il passaggio da uno State a un altro);
              il Context invece non conosce l’insieme delle possibili
              Strategy che potrà ricevere
31
Visitor
     ✦ Il problema
      •   in alcuni casi abbiamo una gerarchia di classi in
          cui la gerarchia è stabile (non capita l’esigenza di
          aggiungere nuove sottoclassi) ma l’insieme di
          operazioni che devono essere effettuate in tutte le
          classi è variabile (capita frequentemente di dover
          aggiungere alla classe base nuove operazioni che
          devono avere un’implementazione diversa in ogni
          sottoclasse)
      •   i meccanismi della programmazione orientata agli
          oggetti sono pensati per semplificare il caso
          contrario: operazioni stabili, e insieme delle classi
          variabile
32
Visitor
     ✦ Esempio del problema
      •   il nostro software gestisce il portale di una
          community di utenti che possono appartenere alle
          seguenti tre categorie:
          ‣   utente anonimo (non registrato)
          ‣   utente normale (registrato con iscrizione gratuita)
          ‣   utente “deluxe” (registrato con iscrizione a pagamento)

      •   il portale definisce una serie di operazioni il cui
          funzionamento è diverso a seconda della
          categoria di utente
      •   l’elenco delle operazioni disponibili cambia molto
          frequentemente
33
Visitor

     ✦ Esempio del problema (continua)
      •   Ad esempio, l’operazione “Invia un messaggio”
          può avere come comportamento:
          ‣   una segnalazione di errore per gli utenti anonimi
          ‣   l’invio condizionato alla verifica del numero massimo di
              messaggi inviabili in un giorno per gli utenti regolari
          ‣   l’invio incondizionato per gli utenti deluxe




34
Visitor
     ✦ Nota
         •     Un problema di questo tipo potrebbe essere
               risolto usando dei metodi con un if a cascata che
               esamina il tipo dell’oggetto:
              if (obj instanceof AnonymousUser)
     	   	       // ...
     	   	    else if (obj instanceof RegularUser)
     	   	    	 // ...
     	   	    else if (obj instanceof DeluxeUser)
     	   	    	 // ...
     	   	    else
     	   	    	 throw new RuntimeException("Unvalid class!");


             • in questo modo però il codice è meno chiaro, e c’è
              una violazione del principio DRY

35
Visitor
     ✦ Soluzione
        ‣ si definisce una interfaccia/classe astratta Visitor, con un
              metodo distinto per ogni classe concreta della gerarchia
          ‣   per ogni operazione da effettuare sugli oggetti (“elementi”)
              della gerarchia, si definisce una sottoclasse concreta di
              Visitor i cui metodi implementano il tipo di operazione da
              effettuare su ciascun tipo di elemento
          ‣   nella classe base della gerarchia si definisce un metodo
              astratto “accept” che riceve come parametro un Visitor
          ‣   le classi concrete della gerarchia implementano il metodo
              accept richiamando il metodo del Visitor che corrisponde al
              tipo di elemento in questione, a cui viene passato il
              riferimento all’elemento corrente (this)


36
Visitor
     ✦ Esempio di struttura




37
Visitor
       ✦ Esempio di soluzione

     public abstract class User {
     	 public String getIpAddress() {
     	 	 return "10.0.77.1";
     	 }
     	
     	 public abstract void accept(UserVisitor visitor);
     }




38
Visitor
       ✦ Esempio di soluzione (continua)

     public   interface UserVisitor {
     	 void   visitAnonymous(AnonymousUser user);
     	 void   visitRegular(RegularUser user);
     	 void   visitDeluxe(DeluxeUser user);
     }




39
Visitor
       ✦ Esempio di soluzione (continua)

     public class AnonymousUser extends User {
     	 public void accept(UserVisitor visitor) {
     	 	 visitor.visitAnonymous(this);
     	 }
     }




40
Visitor
       ✦ Esempio di soluzione (continua)
     public abstract class NamedUser extends User {
     	 private String name;
     	 public NamedUser(String name) {
     	 	 this.name = name;
     	 }
     	
     	 public String getName() {
     	 	 return name;
     	 }
     }




41
Visitor
        ✦ Esempio di soluzione (continua)
     public class RegularUser extends NamedUser {
     	 public static final int DAILY_CREDITS=100;
     	 private int credits;
     	 public RegularUser(String name) {
     	 	 super(name);
     	 	 credits=DAILY_CREDITS;
     	 }
     	 public void accept(UserVisitor visitor) {
     	 	 visitor.visitRegular(this);
     	 }
     	 public int getCredits() {
     	 	 return credits;
     	 }
     	 public void consumeCredits(int amount) {
     	 	 credits -= amount;
     	 }
     	 public void restoreCredits() {
     	 	 credits=DAILY_CREDITS;
     	 }
     }


42
Visitor
       ✦ Esempio di soluzione (continua)
     public class DeluxeUser extends NamedUser {
     	 private String creditCard;
     	 public DeluxeUser(String name, String creditCard) {
     	 	 super(name);
     	 	 this.creditCard=creditCard;
     	 }
     	 public void accept(UserVisitor visitor) {
     	 	 visitor.visitDeluxe(this);
     	 }
     	 public void pay(double amount) {
     	 	 System.out.println("User "+getName()+" has paid "+amount+
     	 	 	 	 " euros with card n. "+creditCard);
     	 }
     }


43
Visitor
     ✦ Esempio di soluzione (continua)

 public class SendMessageVisitor implements UserVisitor {
 	 public static final int MESSAGE_CREDITS=3;
 	 private String receiver, body;
 	 public SendMessageVisitor(String receiver, String body) {
 	 	 this.receiver=receiver;
 	 	 this.body=body;
 	 }
 	 public void visitAnonymous(AnonymousUser user) {
 	 	 System.out.print(user.getIpAddress());
 	 	 System.out.println(", non sei autorizzato a mandare messaggi!");
 	 }
    // continua ...




44
Visitor
         ✦ Esempio di soluzione (continua)
         // ... continua
     	   public void visitRegular(RegularUser user) {
     	   	 if (user.getCredits()>=MESSAGE_CREDITS) {
     	   	 	 System.out.print("Messaggio inviato da "+user.getName());
     	   	 	 System.out.println(" a "+receiver+": "+body);
     	   	 	 user.consumeCredits(MESSAGE_CREDITS);
     	   	 } else {
     	   	 	 System.out.print(user.getName());
     	   	 	 System.out.println(", hai esaurito i crediti a tua disposizione.");
     	   	 }
     	   }
     	   public void visitDeluxe(DeluxeUser user) {
     	   	 System.out.println("Esimio commendator "+user.getName()+",");
     	   	 System.out.println(" il suo messaggio: "+body);
     	   	 System.out.println(+receiver);
     	   	 System.out.println("Le porgiamo umilmente i nostri saluti.");
     	   }
     }



45
Visitor
         ✦ Esempio di soluzione (continua)


             // ...
     	   	   UserVisitor send=new SendMessageVisitor("Pippo", "ciao!");
     	   	   User a=new AnonymousUser();
     	   	   User b=new RegularUser("Paperino");
     	   	   User c=new DeluxeUser("Gastone", "PAP131313");
     	   	   a.accept(send);
     	   	   b.accept(send);
     	   	   c.accept(send);
             // ...




46
Visitor

     ✦ Conseguenze
      •   è semplice aggiungere nuove operazioni che
          abbiano un effetto diverso su ciascun tipo di
          elemento
      •   il codice delle operazioni non contiene “if” a
          cascata che controllano esplicitamente il tipo
          dell’oggetto
      •   PROBLEMA: è difficile aggiungere nuovi tipi di
          elemento (occorre cambiare tutti i Visitor)



47
Visitor
     ✦ Nota
      •   in un certo senso il pattern Visitor serve ad
          aggirare una limitazione del polimorfismo in Java
          (e nella maggior parte dei linguaggi OO):
          ‣   la scelta polimorfica del metodo da eseguire può dipendere
              dal tipo di un solo oggetto, il ricevente (si parla di single
              dispatch); invece negli esempi di applicabilità del pattern
              Visitor si vuole fare in modo che il metodo eseguito
              dipenda da DUE oggetti: l’elemento e l’operazione (double
              dispatch)

      •   in alcuni linguaggi di programmazione (es.
          Common Lisp, Dylan, Groovy, Perl 6) il multiple
          dispatch è supportato direttamente dal
          linguaggio, e non è quindi necessario questo
          pattern
48

Weitere ähnliche Inhalte

Was ist angesagt?

Lezione 11: Accesso ai RESTful Web Services in Java
Lezione 11: Accesso ai RESTful Web Services in JavaLezione 11: Accesso ai RESTful Web Services in Java
Lezione 11: Accesso ai RESTful Web Services in JavaAndrea Della Corte
 
Lezione 2: Pianificazione in Extreme Programming
Lezione 2: Pianificazione in Extreme ProgrammingLezione 2: Pianificazione in Extreme Programming
Lezione 2: Pianificazione in Extreme ProgrammingAndrea Della Corte
 
Lezione 10: Web Service in Java (2)
Lezione 10: Web Service in Java (2)Lezione 10: Web Service in Java (2)
Lezione 10: Web Service in Java (2)Andrea Della Corte
 
Lezione 9: Web Service in Java
Lezione 9: Web Service in JavaLezione 9: Web Service in Java
Lezione 9: Web Service in JavaAndrea Della Corte
 
Non solo Django: MVC orientato agli oggetti con Plone e Zope Toolkit
Non solo Django: MVC orientato agli oggetti con Plone e Zope ToolkitNon solo Django: MVC orientato agli oggetti con Plone e Zope Toolkit
Non solo Django: MVC orientato agli oggetti con Plone e Zope ToolkitMaurizio Delmonte
 
Design pattern template method
Design pattern template methodDesign pattern template method
Design pattern template methodNelson Firmani
 
Closure Visto Da Vicino
Closure Visto Da VicinoClosure Visto Da Vicino
Closure Visto Da Vicinodavide ficano
 
Lezione design patterns 2011 (Peron)
Lezione design patterns 2011 (Peron)Lezione design patterns 2011 (Peron)
Lezione design patterns 2011 (Peron)lukebonham
 
Introduzione alla programmazione Android - Android@tulug lezione 4
Introduzione alla programmazione Android - Android@tulug lezione 4Introduzione alla programmazione Android - Android@tulug lezione 4
Introduzione alla programmazione Android - Android@tulug lezione 4Ivan Gualandri
 
Programmazione funzionale e Stream in Java
Programmazione funzionale e Stream in JavaProgrammazione funzionale e Stream in Java
Programmazione funzionale e Stream in JavaCristina Attori
 

Was ist angesagt? (18)

Lezione 11: Accesso ai RESTful Web Services in Java
Lezione 11: Accesso ai RESTful Web Services in JavaLezione 11: Accesso ai RESTful Web Services in Java
Lezione 11: Accesso ai RESTful Web Services in Java
 
Lezione 2: Pianificazione in Extreme Programming
Lezione 2: Pianificazione in Extreme ProgrammingLezione 2: Pianificazione in Extreme Programming
Lezione 2: Pianificazione in Extreme Programming
 
Design Pattern
Design PatternDesign Pattern
Design Pattern
 
Lezione 10: Web Service in Java (2)
Lezione 10: Web Service in Java (2)Lezione 10: Web Service in Java (2)
Lezione 10: Web Service in Java (2)
 
Corso Java
Corso JavaCorso Java
Corso Java
 
Corso Java 2 - AVANZATO
Corso Java 2 - AVANZATOCorso Java 2 - AVANZATO
Corso Java 2 - AVANZATO
 
Lezione 9: Web Service in Java
Lezione 9: Web Service in JavaLezione 9: Web Service in Java
Lezione 9: Web Service in Java
 
Java OCA teoria 1
Java OCA teoria 1Java OCA teoria 1
Java OCA teoria 1
 
Corso Javascript
Corso JavascriptCorso Javascript
Corso Javascript
 
Corso progettazione
Corso progettazioneCorso progettazione
Corso progettazione
 
Non solo Django: MVC orientato agli oggetti con Plone e Zope Toolkit
Non solo Django: MVC orientato agli oggetti con Plone e Zope ToolkitNon solo Django: MVC orientato agli oggetti con Plone e Zope Toolkit
Non solo Django: MVC orientato agli oggetti con Plone e Zope Toolkit
 
Design pattern template method
Design pattern template methodDesign pattern template method
Design pattern template method
 
Java OCA teoria 4
Java OCA teoria 4Java OCA teoria 4
Java OCA teoria 4
 
Closure Visto Da Vicino
Closure Visto Da VicinoClosure Visto Da Vicino
Closure Visto Da Vicino
 
Lezione design patterns 2011 (Peron)
Lezione design patterns 2011 (Peron)Lezione design patterns 2011 (Peron)
Lezione design patterns 2011 (Peron)
 
Portlet JSR168/286
Portlet JSR168/286Portlet JSR168/286
Portlet JSR168/286
 
Introduzione alla programmazione Android - Android@tulug lezione 4
Introduzione alla programmazione Android - Android@tulug lezione 4Introduzione alla programmazione Android - Android@tulug lezione 4
Introduzione alla programmazione Android - Android@tulug lezione 4
 
Programmazione funzionale e Stream in Java
Programmazione funzionale e Stream in JavaProgrammazione funzionale e Stream in Java
Programmazione funzionale e Stream in Java
 

Ähnlich wie Lezione 9: Design Pattern Comportamentali

Corso Object Oriented Analysis and Design
Corso Object Oriented Analysis and DesignCorso Object Oriented Analysis and Design
Corso Object Oriented Analysis and DesignK-Tech Formazione
 
Programmazione mobile: ANDROID
Programmazione mobile: ANDROIDProgrammazione mobile: ANDROID
Programmazione mobile: ANDROIDPaolo Tosato
 
Javascript - 7 | WebMaster & WebDesigner
Javascript - 7 | WebMaster & WebDesignerJavascript - 7 | WebMaster & WebDesigner
Javascript - 7 | WebMaster & WebDesignerMatteo Magni
 
PowerMock TDD User Group Milano
PowerMock TDD User Group MilanoPowerMock TDD User Group Milano
PowerMock TDD User Group MilanoMassimo Groppelli
 
PyPaPi Qt Java Framework
PyPaPi Qt Java FrameworkPyPaPi Qt Java Framework
PyPaPi Qt Java FrameworkTiziano Lattisi
 
Introduzione a JavaScript
Introduzione a JavaScriptIntroduzione a JavaScript
Introduzione a JavaScriptGiovanni Buffa
 
Introduzione ai Big Data e alla scienza dei dati - Big Data
Introduzione ai Big Data e alla scienza dei dati - Big DataIntroduzione ai Big Data e alla scienza dei dati - Big Data
Introduzione ai Big Data e alla scienza dei dati - Big DataVincenzo Manzoni
 
09 - Programmazione: Ingegneria del Codice
09 - Programmazione: Ingegneria del Codice09 - Programmazione: Ingegneria del Codice
09 - Programmazione: Ingegneria del CodiceMajong DevJfu
 
Dependency injection: the good parts
Dependency injection:  the good partsDependency injection:  the good parts
Dependency injection: the good partsMassimo Groppelli
 
Javascript - 7 | WebMaster & WebDesigner
Javascript - 7 | WebMaster & WebDesignerJavascript - 7 | WebMaster & WebDesigner
Javascript - 7 | WebMaster & WebDesignerMatteo Magni
 
Silverlight m v-vm @ DotNetteria
Silverlight m v-vm @ DotNetteriaSilverlight m v-vm @ DotNetteria
Silverlight m v-vm @ DotNetteriaMauro Servienti
 
How To React - Aspetti avanzati della gestione dello stato
How To React - Aspetti avanzati della gestione dello statoHow To React - Aspetti avanzati della gestione dello stato
How To React - Aspetti avanzati della gestione dello statoAldoNoschese
 

Ähnlich wie Lezione 9: Design Pattern Comportamentali (15)

pattern
patternpattern
pattern
 
Corso Object Oriented Analysis and Design
Corso Object Oriented Analysis and DesignCorso Object Oriented Analysis and Design
Corso Object Oriented Analysis and Design
 
Programmazione mobile: ANDROID
Programmazione mobile: ANDROIDProgrammazione mobile: ANDROID
Programmazione mobile: ANDROID
 
Javascript - 7 | WebMaster & WebDesigner
Javascript - 7 | WebMaster & WebDesignerJavascript - 7 | WebMaster & WebDesigner
Javascript - 7 | WebMaster & WebDesigner
 
PowerMock TDD User Group Milano
PowerMock TDD User Group MilanoPowerMock TDD User Group Milano
PowerMock TDD User Group Milano
 
PyPaPi Qt Java Framework
PyPaPi Qt Java FrameworkPyPaPi Qt Java Framework
PyPaPi Qt Java Framework
 
Introduzione a JavaScript
Introduzione a JavaScriptIntroduzione a JavaScript
Introduzione a JavaScript
 
Introduzione ai Big Data e alla scienza dei dati - Big Data
Introduzione ai Big Data e alla scienza dei dati - Big DataIntroduzione ai Big Data e alla scienza dei dati - Big Data
Introduzione ai Big Data e alla scienza dei dati - Big Data
 
Jug 30 10 04 Jdo
Jug 30 10 04 JdoJug 30 10 04 Jdo
Jug 30 10 04 Jdo
 
m-v-vm @ UgiAlt.Net
m-v-vm @ UgiAlt.Netm-v-vm @ UgiAlt.Net
m-v-vm @ UgiAlt.Net
 
09 - Programmazione: Ingegneria del Codice
09 - Programmazione: Ingegneria del Codice09 - Programmazione: Ingegneria del Codice
09 - Programmazione: Ingegneria del Codice
 
Dependency injection: the good parts
Dependency injection:  the good partsDependency injection:  the good parts
Dependency injection: the good parts
 
Javascript - 7 | WebMaster & WebDesigner
Javascript - 7 | WebMaster & WebDesignerJavascript - 7 | WebMaster & WebDesigner
Javascript - 7 | WebMaster & WebDesigner
 
Silverlight m v-vm @ DotNetteria
Silverlight m v-vm @ DotNetteriaSilverlight m v-vm @ DotNetteria
Silverlight m v-vm @ DotNetteria
 
How To React - Aspetti avanzati della gestione dello stato
How To React - Aspetti avanzati della gestione dello statoHow To React - Aspetti avanzati della gestione dello stato
How To React - Aspetti avanzati della gestione dello stato
 

Mehr von Andrea Della Corte

Lezione 8: Introduzione ai Web Service
Lezione 8: Introduzione ai Web ServiceLezione 8: Introduzione ai Web Service
Lezione 8: Introduzione ai Web ServiceAndrea Della Corte
 
Lezione 7: Remote Method Invocation e SSL
Lezione 7: Remote Method Invocation e SSLLezione 7: Remote Method Invocation e SSL
Lezione 7: Remote Method Invocation e SSLAndrea Della Corte
 
Lezione 6: Remote Method Invocation
Lezione 6: Remote Method InvocationLezione 6: Remote Method Invocation
Lezione 6: Remote Method InvocationAndrea Della Corte
 
Lezione12: Autenticazione e gestione delle sessioni in REST
Lezione12: Autenticazione e gestione delle sessioni in RESTLezione12: Autenticazione e gestione delle sessioni in REST
Lezione12: Autenticazione e gestione delle sessioni in RESTAndrea Della Corte
 
Lezione 4: Comunicazione con UDP
Lezione 4: Comunicazione con UDPLezione 4: Comunicazione con UDP
Lezione 4: Comunicazione con UDPAndrea Della Corte
 

Mehr von Andrea Della Corte (11)

Lezione 1: I metodi agili
Lezione 1: I metodi agiliLezione 1: I metodi agili
Lezione 1: I metodi agili
 
Lezione 5: Socket SSL/ TLS
Lezione 5: Socket SSL/ TLSLezione 5: Socket SSL/ TLS
Lezione 5: Socket SSL/ TLS
 
Lezione 8: Introduzione ai Web Service
Lezione 8: Introduzione ai Web ServiceLezione 8: Introduzione ai Web Service
Lezione 8: Introduzione ai Web Service
 
Lezione 7: Remote Method Invocation e SSL
Lezione 7: Remote Method Invocation e SSLLezione 7: Remote Method Invocation e SSL
Lezione 7: Remote Method Invocation e SSL
 
Lezione 6: Remote Method Invocation
Lezione 6: Remote Method InvocationLezione 6: Remote Method Invocation
Lezione 6: Remote Method Invocation
 
Lezione12: Autenticazione e gestione delle sessioni in REST
Lezione12: Autenticazione e gestione delle sessioni in RESTLezione12: Autenticazione e gestione delle sessioni in REST
Lezione12: Autenticazione e gestione delle sessioni in REST
 
Lezione 1: I/O in Java
Lezione 1: I/O in JavaLezione 1: I/O in Java
Lezione 1: I/O in Java
 
Lezione 3: Connessioni TCP
Lezione 3: Connessioni TCPLezione 3: Connessioni TCP
Lezione 3: Connessioni TCP
 
Lezione 4: Comunicazione con UDP
Lezione 4: Comunicazione con UDPLezione 4: Comunicazione con UDP
Lezione 4: Comunicazione con UDP
 
Tutorial Matlab 2009
Tutorial Matlab 2009Tutorial Matlab 2009
Tutorial Matlab 2009
 
Introduzione ai CRM
Introduzione ai CRMIntroduzione ai CRM
Introduzione ai CRM
 

Lezione 9: Design Pattern Comportamentali

  • 1. Lezione 25: Design Pattern Comportamentali Corso di Ingegneria del Software Laurea Magistrale in Ing. Informatica Università degli Studi di Salerno 1
  • 2. Outline ✦ Design Pattern Comportamentali • Observer (continuazione) • State • Strategy • Visitor 2
  • 4. Observer ✦ Conseguenze • il Subject è disaccoppiato dagli oggetti che dipendono da esso (maggiore riusabilità e testabilità) • comunicazione “broadcast”: il Subject non sa quanti oggetti dipendono da esso 4
  • 5. Observer ✦ Note • tutti gli Observer sono informati di tutte le variazioni dello stato del Subject; in alcuni casi questo può essere inefficiente ‣ una variante del pattern prevede che i possibili cambiamenti di stato siano divisi in categorie (“Topic”), e ciascun Observer specifica all’atto della registrazione quali sono i topic a cui è interessato 5
  • 6. Observer ✦ Observer vs Chain of Responsibility • i due pattern soddisfano un’esigenza simile, però ‣ nella Chain of Responibility si assume che uno solo degli handler gestisca effettivamente la richiesta; inoltre c’è una priorità tra gli handler: ciascun handler ha la possibilità di “filtrare” le richieste che arrivano agli handler successivi ‣ gli Observer invece sono tutti allo stesso livello, e tipicamente tutti gli observer rispondono in qualche modo a ciascun cambiamento (almeno per i Topic a cui sono registrati) 6
  • 7. State ✦ Il problema • un oggetto (Context) può trovarsi in più “stati” diversi, e il comportamento di alcune operazioni deve dipendere dallo stato in cui l’oggetto si trova • si vuole evitare che la dipendenza del comportamento dallo stato sia “cablata” all’interno dei metodi dell’oggetto perché ciò renderebbe difficile cambiare/estendere l’insieme degli stati 7
  • 8. State ✦ Esempio del problema • un oggetto che rappresenta un file può essere in uno dei seguenti stati: ‣ chiuso ‣ aperto per operazioni di lettura ‣ aperto per operazioni di scrittura ‣ aperto per operazioni di lettura e scrittura • le operazioni read e write, a seconda dello stato, svolgono la loro funzione oppure lanciano un’eccezione 8
  • 9. State ✦ Esempio del problema • in un programma di disegno l’utente può selezionare diversi strumenti ‣ matita ‣ gomma ‣ pennello ‣ disegno di linee ‣ ecc. • il programma deve rispondere agli eventi del mouse in modo diverso a seconda dello strumento selezionato 9
  • 10. State ✦ Soluzione • lo stato del Context viene trasformato in un oggetto, che implementa un’interfaccia State con le operazioni che devono essere eseguite diversamente per ogni stato • per ogni possibile stato si definisce una sottoclasse concreta di State • il Context mantiene un riferimento all’oggetto che rappresenta lo stato corrente; per cambiare stato viene cambiato questo riferimento • il Context delega allo stato corrente le operazioni che sono dipendenti dallo stato 10
  • 11. State ✦ Esempio di struttura 11
  • 12. State ✦ Esempio di soluzione import java.awt.*; public abstract class Tool { public void mouseDown(Graphics g, int x, int y) { } public void dragTo(Graphics g, int x, int y) { } public void mouseUp(Graphics g, int x, int y) { } } 12
  • 13. State ✦ Esempio di soluzione (continua) import java.awt.Graphics; public class LineTool extends Tool { private int prevX, prevY; public void mouseDown(Graphics g, int x, int y) { prevX = x; prevY = y; } public void mouseUp(Graphics g, int x, int y) { g.drawLine(prevX, prevY, x, y); } } 13
  • 14. State ✦ Esempio di soluzione (continua) import java.awt.Graphics; public class FreehandTool extends Tool { private int prevX, prevY; public void mouseDown(Graphics g, int x, int y) { prevX = x; prevY = y; } public void dragTo(Graphics g, int x, int y) { g.drawLine(prevX, prevY, x, y); prevX = x; prevY = y; } public void mouseUp(Graphics g, int x, int y) { g.drawLine(prevX, prevY, x, y); } } 14
  • 15. State ✦ Esempio di soluzione (continua) // . . . public class Doodle extends Canvas { private Tool selectedTool; public Doodle() { // . . . addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent evt) { selectedTool.mouseDown(getGraphics(), evt.getX(), evt.getY()); } // . . . }); // . . . } // . . . public void setTool(Tool t) { selectedTool=t; } // . . . } 15
  • 16. State ✦ Conseguenze • la dipendenza dallo stato non è distribuita nel codice di diversi metodi del context, ma è raccolta nei metodi delle implementazioni concrete di State • è semplice modificare il comportamento di uno specifico stato, oppure aggiungere al sistema nuovi stati inizialmente non previsti 16
  • 17. Strategy ✦ Il problema • spesso in un determinato contesto è necessario effettuare un’operazione (o un insieme di operazioni collegate) che può avere implementazioni diverse • si vuole rendere il contesto indipendente da una particolare implementazione dell’operazione 17
  • 18. Strategy ✦ Esempio del problema • in un algoritmo di ordinamento basato su confronti è necessario comparare due oggetti • la comparazione dipende dal tipo di oggetti da ordinare, ma anche per un singolo tipo di oggetti sono possibili diversi criteri di ordinamento, che corrispondono a diverse implementazioni dell’operazione di comparazione • si vuole rendere l’algoritmo di ordinamento indipendente dal modo in cui viene effettuata la comparazione 18
  • 19. Strategy ✦ Soluzione • si definisce una interfaccia Strategy che contiene le operazioni di cui si vuole nascondere l’implementazione • per ogni implementazione si definisce una sottoclasse concreta di Strategy • l’oggetto che rappresenta il contesto (Context) riceve un riferimento a un’istanza di una sottoclasse concreta di Strategy 19
  • 20. Strategy ✦ Esempio di struttura 20
  • 21. Strategy ✦ Esempio di soluzione • L’interfaccia Comparator nella libreria Java package java.util; public interface Comparator { // Confronta due oggetti // restituisce un valore <0, =0 o >0 // a seconda che sia x<y, x=y, x>y int compare(Object x, Object y); // verifica se un altro oggetto è uguale // a questo Comparator boolean equals(Object other); } 21
  • 22. Strategy ✦ Esempio di soluzione (continua) • Gli algoritmi di ordinamento nella libreria Java ricevono come parametro un Comparator public class Collections { // Ordina una lista public static List sort(List list, Comparator order) { // . . . 22
  • 23. Strategy ✦ Conseguenze • è possibile realizzare in modo semplice famiglie di algoritmi simili che differiscono per l’implementazione di alcune operazioni • il contesto può cambiare l’implementazione delle operazioni anche a run time, scegliendo un diverso oggetto Strategy 23
  • 24. Strategy ✦ Template Method vs Strategy • i due pattern risolvono lo stesso problema • differenze: ‣ con Template Method non è necessario creare più oggetti ‣ con Strategy non c’è un’esplosione combinatoria di sottoclassi se il contesto ha più operazioni che devono essere incapsulate indipendentemente ‣ con Strategy l’implementazione delle operazioni incapsulate può essere effettuata a run time ‣ una stessa Strategy può essere utilizzata in contesti diversi 24
  • 25. Strategy ✦ Esempio di implementazione • Rivediamo l’esempio delle operazioni di accumulazione usando il pattern Strategy invece di Template Method • per cominciare, definiamo l’interfaccia Strategy public interface AccumulationStrategy { int initialValue(); int combine(int currentValue, int element); } 25
  • 26. Strategy ✦ Esempio di implementazione (continua) • definiamo ora la classe Accumulator public class Accumulator { private AccumulationStrategy strategy; public Accumulator(AccumulationStrategy strategy) { this.strategy=strategy; } public int compute(int a[], int n) { int value=strategy.initialValue(); int i; for(i=0; i<n; i++) value=strategy.combine(value, a[i]); return value; } } 26
  • 27. Strategy ✦ Esempio di implementazione (continua) • definiamo ora le strategie concrete public class SumStrategy implements AccumulationStrategy { public int initialValue() { return 0; } public int combine(int currentValue, int element) { return currentValue+element; } } 27
  • 28. Strategy ✦ Esempio di implementazione (continua) • definiamo ora le strategie concrete public class ProductStrategy implements AccumulationStrategy { public int initialValue() { return 1; } public int combine(int currentValue, int element) { return currentValue*element; } } 28
  • 29. Strategy ✦ Esempio di implementazione (continua) • definiamo ora le strategie concrete public class CountPositiveStrategy implements AccumulationStrategy { public int initialValue() { return 0; } public int combine(int currentValue, int element) { if (element>0) return currentValue+1; else return currentValue; } } 29
  • 30. Strategy ✦ Esempio di implementazione (continua) • esempio di uso di Accumulator: AccumulationStrategy strategy=new SumStrategy(); Accumulator acc=new Accumulator(strategy); int sum=acc.compute(a,n); 30
  • 31. Strategy ✦ State vs Strategy • i due pattern sono molto simili (da un punto di vista implementativo sono identici) • la differenza è nella finalità: ‣ Strategy serve a parametrizzare un algoritmo, State serve a semplificare l’implementazione di un comportamento complesso ‣ Una Strategy generalmente non cambia durante l’esistenza del Context (anche se è possibile farlo); uno State invece quasi sempre cambia durante l’esecuzione ‣ Di solito il Context conosce tutti i possibili State che sono applicabili (e gestisce il passaggio da uno State a un altro); il Context invece non conosce l’insieme delle possibili Strategy che potrà ricevere 31
  • 32. Visitor ✦ Il problema • in alcuni casi abbiamo una gerarchia di classi in cui la gerarchia è stabile (non capita l’esigenza di aggiungere nuove sottoclassi) ma l’insieme di operazioni che devono essere effettuate in tutte le classi è variabile (capita frequentemente di dover aggiungere alla classe base nuove operazioni che devono avere un’implementazione diversa in ogni sottoclasse) • i meccanismi della programmazione orientata agli oggetti sono pensati per semplificare il caso contrario: operazioni stabili, e insieme delle classi variabile 32
  • 33. Visitor ✦ Esempio del problema • il nostro software gestisce il portale di una community di utenti che possono appartenere alle seguenti tre categorie: ‣ utente anonimo (non registrato) ‣ utente normale (registrato con iscrizione gratuita) ‣ utente “deluxe” (registrato con iscrizione a pagamento) • il portale definisce una serie di operazioni il cui funzionamento è diverso a seconda della categoria di utente • l’elenco delle operazioni disponibili cambia molto frequentemente 33
  • 34. Visitor ✦ Esempio del problema (continua) • Ad esempio, l’operazione “Invia un messaggio” può avere come comportamento: ‣ una segnalazione di errore per gli utenti anonimi ‣ l’invio condizionato alla verifica del numero massimo di messaggi inviabili in un giorno per gli utenti regolari ‣ l’invio incondizionato per gli utenti deluxe 34
  • 35. Visitor ✦ Nota • Un problema di questo tipo potrebbe essere risolto usando dei metodi con un if a cascata che esamina il tipo dell’oggetto: if (obj instanceof AnonymousUser) // ... else if (obj instanceof RegularUser) // ... else if (obj instanceof DeluxeUser) // ... else throw new RuntimeException("Unvalid class!"); • in questo modo però il codice è meno chiaro, e c’è una violazione del principio DRY 35
  • 36. Visitor ✦ Soluzione ‣ si definisce una interfaccia/classe astratta Visitor, con un metodo distinto per ogni classe concreta della gerarchia ‣ per ogni operazione da effettuare sugli oggetti (“elementi”) della gerarchia, si definisce una sottoclasse concreta di Visitor i cui metodi implementano il tipo di operazione da effettuare su ciascun tipo di elemento ‣ nella classe base della gerarchia si definisce un metodo astratto “accept” che riceve come parametro un Visitor ‣ le classi concrete della gerarchia implementano il metodo accept richiamando il metodo del Visitor che corrisponde al tipo di elemento in questione, a cui viene passato il riferimento all’elemento corrente (this) 36
  • 37. Visitor ✦ Esempio di struttura 37
  • 38. Visitor ✦ Esempio di soluzione public abstract class User { public String getIpAddress() { return "10.0.77.1"; } public abstract void accept(UserVisitor visitor); } 38
  • 39. Visitor ✦ Esempio di soluzione (continua) public interface UserVisitor { void visitAnonymous(AnonymousUser user); void visitRegular(RegularUser user); void visitDeluxe(DeluxeUser user); } 39
  • 40. Visitor ✦ Esempio di soluzione (continua) public class AnonymousUser extends User { public void accept(UserVisitor visitor) { visitor.visitAnonymous(this); } } 40
  • 41. Visitor ✦ Esempio di soluzione (continua) public abstract class NamedUser extends User { private String name; public NamedUser(String name) { this.name = name; } public String getName() { return name; } } 41
  • 42. Visitor ✦ Esempio di soluzione (continua) public class RegularUser extends NamedUser { public static final int DAILY_CREDITS=100; private int credits; public RegularUser(String name) { super(name); credits=DAILY_CREDITS; } public void accept(UserVisitor visitor) { visitor.visitRegular(this); } public int getCredits() { return credits; } public void consumeCredits(int amount) { credits -= amount; } public void restoreCredits() { credits=DAILY_CREDITS; } } 42
  • 43. Visitor ✦ Esempio di soluzione (continua) public class DeluxeUser extends NamedUser { private String creditCard; public DeluxeUser(String name, String creditCard) { super(name); this.creditCard=creditCard; } public void accept(UserVisitor visitor) { visitor.visitDeluxe(this); } public void pay(double amount) { System.out.println("User "+getName()+" has paid "+amount+ " euros with card n. "+creditCard); } } 43
  • 44. Visitor ✦ Esempio di soluzione (continua) public class SendMessageVisitor implements UserVisitor { public static final int MESSAGE_CREDITS=3; private String receiver, body; public SendMessageVisitor(String receiver, String body) { this.receiver=receiver; this.body=body; } public void visitAnonymous(AnonymousUser user) { System.out.print(user.getIpAddress()); System.out.println(", non sei autorizzato a mandare messaggi!"); } // continua ... 44
  • 45. Visitor ✦ Esempio di soluzione (continua) // ... continua public void visitRegular(RegularUser user) { if (user.getCredits()>=MESSAGE_CREDITS) { System.out.print("Messaggio inviato da "+user.getName()); System.out.println(" a "+receiver+": "+body); user.consumeCredits(MESSAGE_CREDITS); } else { System.out.print(user.getName()); System.out.println(", hai esaurito i crediti a tua disposizione."); } } public void visitDeluxe(DeluxeUser user) { System.out.println("Esimio commendator "+user.getName()+","); System.out.println(" il suo messaggio: "+body); System.out.println(+receiver); System.out.println("Le porgiamo umilmente i nostri saluti."); } } 45
  • 46. Visitor ✦ Esempio di soluzione (continua) // ... UserVisitor send=new SendMessageVisitor("Pippo", "ciao!"); User a=new AnonymousUser(); User b=new RegularUser("Paperino"); User c=new DeluxeUser("Gastone", "PAP131313"); a.accept(send); b.accept(send); c.accept(send); // ... 46
  • 47. Visitor ✦ Conseguenze • è semplice aggiungere nuove operazioni che abbiano un effetto diverso su ciascun tipo di elemento • il codice delle operazioni non contiene “if” a cascata che controllano esplicitamente il tipo dell’oggetto • PROBLEMA: è difficile aggiungere nuovi tipi di elemento (occorre cambiare tutti i Visitor) 47
  • 48. Visitor ✦ Nota • in un certo senso il pattern Visitor serve ad aggirare una limitazione del polimorfismo in Java (e nella maggior parte dei linguaggi OO): ‣ la scelta polimorfica del metodo da eseguire può dipendere dal tipo di un solo oggetto, il ricevente (si parla di single dispatch); invece negli esempi di applicabilità del pattern Visitor si vuole fare in modo che il metodo eseguito dipenda da DUE oggetti: l’elemento e l’operazione (double dispatch) • in alcuni linguaggi di programmazione (es. Common Lisp, Dylan, Groovy, Perl 6) il multiple dispatch è supportato direttamente dal linguaggio, e non è quindi necessario questo pattern 48