Esercitazione sui Design Pattern



Documenti analoghi
L ambizione dei design pattern (letteralmente schemi di programmazione) è quella di offrire soluzioni a problemi ricorrenti che facilitano lo

Progettazione : Design Pattern Creazionali

Esercitazioni di PROGETTAZIONE DEL SOFTWARE A.A

Design Pattern in Java

Luca Mari, Sistemi informativi applicati (reti di calcolatori) appunti delle lezioni. Architetture client/server: applicazioni server

Programmazione a Oggetti Lezione 10. Ereditarieta

12 - Introduzione alla Programmazione Orientata agli Oggetti (Object Oriented Programming OOP)

appunti delle lezioni Architetture client/server: applicazioni server

Gestione degli eventi in Java

Programmazione Orientata agli Oggetti in Linguaggio Java

Tipi primitivi. Ad esempio, il codice seguente dichiara una variabile di tipo intero, le assegna il valore 5 e stampa a schermo il suo contenuto:

Alcuni Design Pattern in Java

Mobilità di Codice. Massimo Merro Programmazione di Rete 128 / 144

Reflection in Java. Linguaggi Corso M-Z - Laurea in Ingegneria Informatica A.A

DESIGN PATTERN CREAZIONALI INGEGNERIA DEL SOFTWARE INTRODUZIONE SINGLETON. Scopo dei design pattern creazionali

Ottava Esercitazione. introduzione ai thread java mutua esclusione

SWIM v2 Design Document

Modulo 4: Ereditarietà, interfacce e clonazione

INTERFACCE GRAFICHE IN JAVA CON SWING DISPENSE

Uso di JUnit. Fondamenti di informatica Oggetti e Java. JUnit. Luca Cabibbo. ottobre 2012

appunti delle lezioni Architetture client/server: applicazioni client

Socket & RMI Ingegneria del Software - San Pietro

Programmazione Orientata agli Oggetti in Linguaggio Java

Fondamenti di Informatica 1. Prof. B.Buttarazzi A.A. 2010/2011

Luca Mari, Sistemi informativi applicati (reti di calcolatori) appunti delle lezioni. Architetture client/server: applicazioni client

File Server Resource Manager (FSRM)

Concetto di Funzione e Procedura METODI in Java

DESIGN PATTERN STRUTTURALI INGEGNERIA DEL SOFTWARE INTRODUZIONE ADAPTER. Scopo Convertire l interfaccia di una classe in un altra.

Vlan Relazione di Sistemi e Reti Cenni teorici

Tale attività non è descritta in questa dispensa

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 2

Design patterns in Java

La prima applicazione Java. Creazione di oggetti - 1. La prima applicazione Java: schema di esecuzione. Gianpaolo Cugola - Sistemi Informativi in Rete

UML Diagrammi delle classi. UML Diagramma classi 1

Programmazione a Oggetti Modulo B

Ingegneria del Software. Introduzione ai pattern

Object Oriented Programming

Con il termine Sistema operativo si fa riferimento all insieme dei moduli software di un sistema di elaborazione dati dedicati alla sua gestione.

GESTIONE DEI PROCESSI

Esercizi della lezione 5 di Java

PROCEDURA INVENTARIO DI MAGAZZINO di FINE ESERCIZIO (dalla versione 3.2.0)

13. Chain of Responsibility

Realizzazione di una classe con un associazione

7 Esercitazione (svolta): Callback. Polling. Java RMI: callback. Server. Server. Client. Client. due possibilità:

Corso Eclipse. Prerequisiti. 1 Introduzione

Registratori di Cassa

Lezione n.10 LPR- Informatica Applicata RMI CallBacks

Oggetti Lezione 3. aspetti generali e definizione di classi I

Java Virtual Machine

Il Pattern PROXY. Ex presentazione realizzata dallo studente Paolo Melchiori (matricola 65734) nell a.a

Organizzazione della lezione. Lezione 18 Remote Method Invocation - 6. (con callback) L accesso al registry per il rebind()

Raffaella Brighi, a.a. 2005/06. Eventi e listener. Corso di Laboratorio II. A.A

Introduzione alla programmazione Java. Dott. Ing. M. Banci, PhD

Test di unità con JUnit4

Java: Compilatore e Interprete

La gestione dell input/output da tastiera La gestione dell input/output da file La gestione delle eccezioni

Guida Rapida all uso del License Manager di ROCKEY4Smart (V )

MANUALE PARCELLA FACILE PLUS INDICE

Versione 7.0 Taglie e Colori. Negozio Facile

Multithreading in Java. Fondamenti di Sistemi Informativi

Servizi Remoti. Servizi Remoti. TeamPortal Servizi Remoti

Capitolo 13. Interrogare una base di dati

La struttura dati ad albero binario

Basi di dati I. Esercitazione proposta

L applicazione di MVC alla simulazione di ascensore I COMPONENTI DELLE INTERFACCE UTENTE GRAFICHE: PARTE II 1

RMI. Java RMI RMI. G. Prencipe

Database e reti. Piero Gallo Pasquale Sirsi

Main System Monitor Keyboard

SERVIZIO DI MESSAGGISTICA ALL UTENTE. Manuale per l operatore

dall argomento argomento della malloc()

CORSO ACCESS PARTE II. Esistono diversi tipi di aiuto forniti con Access, generalmente accessibili tramite la barra dei menu (?)

Soluzione dell esercizio del 12 Febbraio 2004

I MODULI Q.A.T. PANORAMICA. La soluzione modulare di gestione del Sistema Qualità Aziendale

WG-TRANSLATE Manuale Utente WG TRANSLATE. Pagina 1 di 15

Introduzione. Java. Composizione. Esempio -- composizione. G. Prencipe È qualcosa che abbiamo già visto varie volte

InitZero s.r.l. Via P. Calamandrei, Arezzo

Programmi e Oggetti Software

3. Introduzione all'internetworking

Ingegneria del Software. Presentazione del pattern Proxy

Progettare un Firewall

Guida all uso di Java Diagrammi ER

Corso sul linguaggio Java

Gestione dell interattività: gli eventi

Approccio stratificato

Sistemi Operativi MECCANISMI E POLITICHE DI PROTEZIONE. D. Talia - UNICAL. Sistemi Operativi 13.1

MECCANISMI E POLITICHE DI PROTEZIONE 13.1

Office 2007 Lezione 08

Uno dei pregi di Java è quello di integrare la documentazione con il codice stesso Formato dei commenti:

Inizializzazione degli Host. BOOTP e DHCP

CROSSROAD. Gestione TENTATA VENDITA. Introduzione. Caratteristiche generali. Principali funzionalità modulo supervisore

NOTE OPERATIVE. Prodotto Inaz Download Manager. Release 1.3.0

Transcript:

Esercitazione sui Design Pattern

Pattern Creazionali

Singleton Permette la creazione di una sola istanza della classe all interno dell applicazione Fornisce un metodo con cui ottenere l istanza Il costruttore della classe non deve essere accessibile

Singleton public class Logger { private final static Logger logger = new Logger(); private Logger() { public static Logger getinstance() { return logger; public void log(object o){

Istanza e Singleton costruttore privati public class Logger { private final static Logger logger = new Logger(); private Logger() { public static Logger getinstance() { return logger; public void log(object o){

Istanza e Singleton costruttore privati public class Logger { private final static Logger logger = new Logger(); private Logger() { public static Logger getinstance() { return logger; public void log(object o){ Metodo statico per accedere all istanza

Istanza e Singleton costruttore privati public class Logger { private final static Logger logger = new Logger(); private Logger() { public static Logger getinstance() { return logger; public void log(object o){ Metodo statico per accedere all istanza Metodi dell istanza

Note Non deve essere usato per avere un riferimento globale a un oggetto. Vanno bene per creare oggetti ma non per accedervi Usatelo solo quando serve davvero! E se in futuro volessimo avere più istanze?

Factory Disaccoppia la creazione degli oggetti dall invocazione del costruttore Permette di avere una logica che seleziona il tipo dinamico della nuova istanza Utili quando ci interessa avere una classe che implementi una certa interfaccia ma non ci interessa quale sia nello specifico

Esempio Abbiamo diversi tipi di bottoni, ciascuno specifico per un particolare sistema operativo A noi interessa solamente che venga costruito un bottone Vogliamo gestire nel modo più pulito possibile la creazione del bottone

Soluzione brutta Creazione della nuova istanza gestita dal chiamante La logica di creazione dell oggetto viene mischiata con quella del suo utilizzo Possibili duplicazioni di codice. Va ripetuto ogni volta che ci serve un bottone

Factory La factory si occupa di istanziare il bottone del tipo corretto Possiamo separare il codice di selezione dell istanza e quello che deve usarla

Factory public class ButtonFactory { private final SupportedOperatingSystems os; public ButtonFactory(SupportedOperatingSystems os){ this.os = os; public Button createbutton() { switch (os) { case Windows: return new WindowsButton(); case Linux: return new LinuxButton(); return null;

Factory Configurazione public class ButtonFactory { private final SupportedOperatingSystems os; public ButtonFactory(SupportedOperatingSystems os){ this.os = os; public Button createbutton() { switch (os) { case Windows: return new WindowsButton(); case Linux: return new LinuxButton(); return null;

Factory Configurazione public class ButtonFactory { private final SupportedOperatingSystems os; public ButtonFactory(SupportedOperatingSystems os){ this.os = os; public Button createbutton() { switch (os) { case Windows: return new WindowsButton(); case Linux: return new LinuxButton(); return null; Logica di creazione delle istanze

Client public class Client { public void usebutton() { ButtonFactory factory = new ButtonFactory( SupportedOperatingSystems.Windows); Button button = factory.createbutton();

Client public class Client { public void usebutton() { ButtonFactory factory = new ButtonFactory( SupportedOperatingSystems.Windows); Button button = factory.createbutton(); L utilizzatore non sa quale oggetto è stato creato

Note A volte anziché creare una classe è sufficiente un metodo statico, un factory method

Pattern Strutturali

Adapter Permette di far lavorare assieme classi che hanno interfacce non compatibili L adapter incapsula la classe e fornisce l interfaccia richiesta

Esempio Vogliamo sviluppare una applicazione che permetta l utilizzo di diverse tecnologie di comunicazione, ad esempio Socket e RMI Ovviamente vogliamo evitare il più possibile duplicazioni di codice

Soluzione Scrivere la logica applicativa indipendentemente dal protocollo Implementare le classi per permettere la comunicazione Queste classi devono adattare il comportamento della classe a quello richiesto dal protocollo

Logica applicativa public class ApplicationLogic { public void dosomething(){ public void dosomethingelse(){ Non implementa nulla relativamente ai protocolli di interazione con l esterno

Adapter public class SocketAdapter { private final ApplicationLogic applicationlogic; public SocketAdapter(ApplicationLogic applicationlogic) { this.applicationlogic = applicationlogic; public void messagereceived(string message) { if (message.equals("a")) { applicationlogic.dosomething(); if (message.equals("b")) { applicationlogic.dosomethingelse();

Adapter Logica vera e propria public class SocketAdapter { private final ApplicationLogic applicationlogic; public SocketAdapter(ApplicationLogic applicationlogic) { this.applicationlogic = applicationlogic; public void messagereceived(string message) { if (message.equals("a")) { applicationlogic.dosomething(); if (message.equals("b")) { applicationlogic.dosomethingelse();

Adapter Logica vera e propria public class SocketAdapter { private final ApplicationLogic applicationlogic; public SocketAdapter(ApplicationLogic applicationlogic) { this.applicationlogic = applicationlogic; public void messagereceived(string message) { if (message.equals("a")) { applicationlogic.dosomething(); if (message.equals("b")) { applicationlogic.dosomethingelse(); Gestione del protocollo

Proxy Utile se vogliamo estendere, modificare o personalizzare le operazioni effettuate da una classe In genere permette di risolvere problemi di sicurezza o efficienza

Esempio Aggiungere alla logica applicativa una cache per migliorare l efficienza nella risposta alle richieste degli utenti L interfaccia della cache non cambia rispetto a quella della logica vera e propria

Logica applicativa public class ApplicationLogic implements ApplicationInterface{ @Override public Object performoperation(object parameters) {...

Cache public class CachingProxy implements ApplicationInterface { private final ApplicationInterface application; private final Map<Object, Object> cache; public CachingProxy(ApplicationInterface application) { this.application = application; cache = new HashMap<Object, Object>(); @Override public Object performoperation(object parameter) { if (!cache.containskey(parameter)) { cache.put(parameter,application.performoperation(parameter)); return cache.get(parameter);

Cache Stessa interfaccia public class CachingProxy implements ApplicationInterface { private final ApplicationInterface application; private final Map<Object, Object> cache; public CachingProxy(ApplicationInterface application) { this.application = application; cache = new HashMap<Object, Object>(); @Override public Object performoperation(object parameter) { if (!cache.containskey(parameter)) { cache.put(parameter,application.performoperation(parameter)); return cache.get(parameter);

Cache Stessa interfaccia public class CachingProxy implements ApplicationInterface { private final ApplicationInterface application; private final Map<Object, Object> cache; public CachingProxy(ApplicationInterface application) { this.application = application; cache = new HashMap<Object, Object>(); @Override public Object performoperation(object parameter) { if (!cache.containskey(parameter)) { cache.put(parameter,application.performoperation(parameter)); return cache.get(parameter); Diverso comportamento

Note L utilizzo del proxy non richiede nessuna modifica nel client che lo deve utilizzare Altri esempi di proxy sono le versioni unmodifiable delle collections In quel caso i metodi sono re-implementati per inibire le operazioni di modifica

Decorator Permette di aggiungere funzionalità ad un oggetto Il nuovo comportamento può essere aggiunto a run time Non richiede la creazione di nuove sottoclassi

Esempio Scrivere una applicazione per rappresentare diversi tipi di caffè con diversi ingredienti Potremmo fare diverse sottoclassi, ma ne dovremmo fare troppe La soluzione delle sottoclassi non permetterebbe di aggiungere nuovi ingredienti a run time

Struttura base Interfaccia vista dai client public interface Coffee { String getingredients(); float getcost(); public class SimpleCoffee implements Coffee{ @Override public String getingredients() { return "Coffee"; @Override public float getcost() { return 5; Classe di base, senza nessuna decorazione

Decorazioni public abstract class CoffeeDecorator implements Coffee { private final Coffee decoratedcoffe; public CoffeeDecorator(Coffee decoratedcoffee) { this.decoratedcoffe = decoratedcoffee; @Override public float getcost(){ return decoratedcoffe.getcost(); Contiene un oggetto (anche con altre decorazioni) e permette di aggiungergli @Override public String getingredients() { return decoratedcoffe.getingredients(); decorazioni

Una decorazione public class Milk extends CoffeeDecorator { public Milk(Coffee decoratedcoffee) { super(decoratedcoffee); @Override public float getcost() { return super.getcost() +.5f; @Override public String getingredients() { return super.getingredients() + " Milk";

Un altra decorazione public class Whip extends CoffeeDecorator { public Whip(Coffee decoratedcoffee) { super(decoratedcoffee); @Override public float getcost() { return super.getcost() + 1.0f; @Override public String getingredients() { return super.getingredients() + " Whip";

Come le usa il client public class Client { public static void main(string args[]) { Coffee coffe = new SimpleCoffee(); Coffee decoratedcoffee = new Milk(coffe); decoratedcoffee.getcost(); // 5.5 decoratedcoffee.getingredients();// Coffee Milk decoratedcoffee = new Whip(decoratedCoffee); decoratedcoffee.getcost(); // 6.5 decoratedcoffee.getingredients();// Coffee Milk Whip

Note Un approccio simile è usato nelle classi per l input/output di Java: stream, writer, reader Oltre a modificare il comportamento è possibile anche aggiungere nuovi comportamenti Decorator è simile a Proxy, ma permette di comporre diversi comportamenti

Pattern Comportamentali

Strategy Permette di variare gli algoritmi utilizzati nell implementazione della classe La classe base richiede una strategia esterna per portare a termine correttamente il suo compito L abbiamo visto con l ordinamento che richiede la sua strategia di comparazione tra una coppia di elementi

Esempio Vogliamo scrivere il codice per rappresentare un robot che può avere diverse strategie per gestire il suo comportamento Vogliamo fare sì che i comportamenti possano cambiare mentre la nostra applicazione è in esecuzione

Robot public class Robot { private Behavior behavior; public Robot(Behavior behavior) { this.behavior = behavior; public void changebehavior(behavior behavior) { this.behavior = behavior; public void move() { behavior.move();

Comportamenti public interface Behavior { void move(); public class DefensiveBehavior implements Behavior { @Override public void move() { System.out.println("Defensive behavior"); public class AggressiveBehavior implements Behavior { @Override public void move() { System.out.println("Aggressive behavior");

Note La strategia può definire anche solo una parte del comportamento della classe (Come nel caso dell ordinamento)

Observer Utile per gestire il paradigma ad eventi Permette di gestire dinamicamente l accoppiamento tra sorgenti di eventi e classi che devono reagire quando questi si verificano

Come funziona Si ha una classe Osservabile (in Java si può implementare l interfaccia Observable) Si hanno degli oggetti Osservatori (in Java si può implementare l interfaccia Observer)

Observable (Java) Si trova nel package java.util È l interfaccia implementata dal Subject Fornisce metodi per registrare gli Observer: addobserver(observer o) removeobserver(observer o) Fornisce metodi per notificare eventi agli Observer quando qualcosa nell oggetto Observable cambia: notifyobserver(object arg)

Observer (Java) È un interfaccia implementata dalle classi che possono ricevere notifiche di eventi da parte di classi Observable. Ha un solo metodo: update(observable o, Object arg) Il metodo è invocato quando si verifica un cambiamento nell oggetto osservato.

Esempio: conto corrente public class ObserverExample { public static void main(string args[]) { Conto conto = new Conto(); SaldoObserver saldoobserver = new SaldoObserver(); conto.addobserver(saldoobserver); conto.aggiornasaldo(30); public lass SaldoObserver implements Observer { public void update(observable conto, Object saldo) { System.out.println("ricevuto aggiornamento saldo: " + saldo); public class Conto extends Observable { private Integer saldo = 0; public void aggiornasaldo(integer saldo) { this.saldo = saldo; setchanged(); notifyobservers(this.saldo);

Note Il pattern observer è utilizzato nel pattern Model View Controller per notificare alla View eventi generati nel Model e nel Controller.

Model-view-controller

Separation of concerns Controller View Model

Model Incapsula lo stato dell applicazione Deve permettere di accedere ai dati Deve notificare i cambiamenti dello stato

View Deve mostrare il modello Gestisce l interazione con l utente

Controller Rappresenta la logica applicativa Collega le azioni dell utente con modifiche allo stato Sceglie cosa deve essere mostrato

Come interagiscono? Controller Azioni dell utente Seleziona una vista Modifica lo stato View Richiede informazioni Notifica cambiamenti Model

MVC: un possibile class diagram

Come si realizza? Programmazione ad eventi per gestire la comunicazione tra i componenti

Eventi Azioni dell utente Notifiche da model e controller Sono delle classi e contengono delle informazioni dettagliate sull evento

Esempio MouseEvent Evento già definito nelle librerie grafiche di Java Contiene informazioni sull evento: tipo (Click, movimento,...) quale bottone è stato cliccato posizione del puntatore

Ascoltatori Si mettono in ascolto di un evento Devono avere dei metodi per poter reagire agli eventi Possono esserci più ascoltatori per un evento

Esempio public interface MouseListener{ public void mouseclicked(mouseevent e); public void mouseentered(mouseevent e); public void mouseexited(mouseevent e); public void mousepressed(mouseevent e); public void mousereleased(mouseevent e); Un listener deve implementare questa interfaccia e reagire nel modo opportuno agli eventi ricevuti come parametri

Sorgenti di eventi Notificano gli eventi agli interessati La notifica avviene invocando i metodi sugli ascoltatori Devono avete un metodo per permettere la registrazione degli ascoltatori

Esempio public class EventSource{ private List<EventListener> listeners; public void registerlistener(eventlistener listener){ listeners.add(listener); private void notifylisteners(event e){ for(eventlistener listener : listeners){ listener.eventhappened(e); public void foo(){ /* Viene generato un evento e inviata la notifica*/ notifylisteners(new Event(...));

Logica ed interfaccia Logica ed interfaccia utente devono essere separate Servono due interfacce: Controller-Model/View aggiornare la visualizzazione View/Controller-Model inviare i comandi e le richieste

Cosa passare SEMPRE oggetti che rappresentano eventi o creati appositamente Oggetti modificabili del modello NON devono arrivare all interfaccia

Soluzioni Interfacce limitate (Solo metodi di visualizzazione) Oggetti immutabili Oggetti creati appositamente per la visualizzazione

Applicazioni distribuite Esempio di uso di MVC in una applicazione client/server in cui: la logica e i dati sono gestiti dal server l interazione è gestita dal client Nota: il modo presentato non è l unico!

Applicazioni distribuite Server Client Server Controller Client Controller Network Abstraction Interfaces Model View

Possibile soluzione Il Model viene implementato interamente nel server. La View viene implementata interamente nel client. Il Controller viene implementato con un componente nel server e uno nel client. L astrazione di rete mette a disposizione delle interfacce per permettere ai componenti del client di comunicare con i componenti del server.

Riconoscere un buon design Deve essere possibile modificare il tipo di rete (Socket o RMI) senza modificare Model e View. Deve essere possibile modificare il tipo di view (grafica o testuale) senza modificare Model, Server Controller, e le astrazioni di rete. Suggerimento: disaccoppiare la parti di Model/ View/Controller (e le astrazioni di rete) utilizzando opportune interfacce e/o design pattern!