Modulo 15 Design Patterns Creazionali Categoria Creational Questa categoria raccoglie i pattern che forniscono un'astrazione per il processo di istanziazione. Questi pattern permettono di rendere un sistema indipendente da come sono creati, rappresentati e composti gli oggetti al suo interno. Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 2 1 I Design Pattern Creazionali Design Patterns Builder Descrizione Separa la costruzione di un oggetto complesso dalla sua rappresentazione in modo da poter usare lo stesso processo di costruzione per altre rappresentazioni Abstract Factory Provvede ad un interfaccia per creare famiglie di oggetti in relazione senza specificare le loro classi concrete Factory Method Definisce un interfaccia per creare un oggetto ma lascia decidere alle sottoclassi quale classe istanziare Prototype Specifica il tipo di oggetto da creare usando un istanza prototipo e crea nuovi oggetti copiando questo prototipo Singleton Assicura che la classe abbia una sola istanza e provvede un modo di accesso Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 3 Singleton Scopo: Assicurare che una classe abbia una sola istanza, e fornire un punto globale di accesso ad essa. Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 4 2 Singleton (Struttura) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 5 Singleton (Esempio) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 6 3 Singleton: Esercizio Un applicativo deve istanziare un oggetto che gestisce una stampante. Questo oggetto deve essere unico, vale dire, deve esserci soltanto una sola istanza di esso, altrimenti, potrebbero risultare dei problemi nella gestione della risorsa. Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 7 Singleton: Esercizio Diagramma UML: Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 8 4 Singleton: Implementazione in Java (1) Singleton creato da un metodo statico public class PrinterSpooler { private static PrinterSpooler instance; private PrinterSpooler() {} public static PrinterSpooler getInstance() { if ( instance==null) { instance = new PrinterSpooler(); } return instance; } public void print (String msg) { System.out.println( msg ); } } Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 9 Singleton: Implementazione in Java (2) Esempio di utilizzo ... PrinterSpooler theUnique = PrinterSpooler.getInstance(); theUnique.print( somethingToPrint ); //if we try this: PrinterSpooler mayBeOther = PrinterSpooler.getInstance(); //then... if( theUnique != mayBeOther ) /* FALSE */ … Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 10 5 Singleton: Implementazione in Java (3) Singleton come classe statica (Booch Utility) public static class PrinterSpooler { private PrinterSpooler() {} public static void print (String msg) { System.out.println( msg ); } } Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 11 Singleton: Implementazione in Java (4) Esempio di utilizzo ... PrinterSpooler.print( somethingToPrint ); ... Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 12 6 Prototype Scopo: Specificare le tipologie di oggetti da creare utilizzando un’istanza prototipo, e creare nuovi oggetti copiando questo prototipo. Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 13 Prototype (Struttura) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 14 7 Prototype (Esempio) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 15 Prototype: Esercizio (2) Si pensi alla creazione di uno schedulatore in grado di eseguire operazioni su oggetti che rappresentano istanti di tempo. Si ipotizzi che una delle operazioni da realizzare sia definire l’ora di termine di una attività, utilizzando come dati di input la sua ora di inizio e un numero intero corrispondente alla durata dell’attività. Questa operazione deve restituire un nuovo oggetto che rappresenti l’ora di termine, calcolata come la somma della ora di inizio e ladurata dell’attività: Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 16 8 Prototype: Esercizio (2) Si vuole progettare lo schedulatore in modo che sia in grado di ricevere come input (ora inizio) oggetti di diverse classi che implementino una particolare interfaccia. Si vuole che l’output dello schedulatore sia un oggetto contenente il risultato della schedulazione, che appartenga alla stessa classe dell’oggetto ricevuto come input. Il problema è che al momento di progettare lo schedulatore solo si ha conoscenza dell’interfaccia, non delle specifiche classi su cui dovrà agire. Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 17 Prototype: Applicazione del pattern Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 18 9 Prototype: Implementazione in Java (1) Definizione di CloneableTime public abstract class CloneableTime implements Cloneable { public abstract void setTime(int hr, int min, int sec); public abstract int getHours(); public abstract int getMinutes(); public abstract int getSeconds(); public CloneableTime cloneItself() throws CloneNotSupportedException { CloneableTime theClone = (CloneableTime) super.clone(); theClone.setTime( 0, 0, 0 ); return theClone; } } Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 19 Prototype: Implementazione in Java (2) Implementazione di TimeImplementationC1 public class TimeImplementationC1 extends CloneableTime { private int hr, min, sec; public void setTime(int hr, int min, int sec) { this.hr = hr; this.min = min; this.sec = sec; } public int getHours() { return hr; } public int getMinutes() { return min; } public int getSeconds() { return sec; } } Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 20 10 Prototype: Implementazione in Java (3) Implementazione di TimeImplementationC2 public class TimeImplementationC2 extends CloneableTime { private int secs; public void setTime(int hr, int min, int sec) { secs = hr * 3600 + min * 60 + sec; } public int getHours() { return secs / 3600; } public int getMinutes() { return (secs - getHours()*3600) / 60; } public int getSeconds() { return secs % 60; } Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 } 21 Prototype: Implementazione in Java (4) Implementazione di SchedulerC public class SchedulerC { public static CloneableTime calculateEnd( CloneableTime start, int hours ) throws CloneNotSupportedException { int hr = start.getHours() + hours; hr = hr < 24 ? hr : hr - 24; CloneableTime endTime = start.cloneItself(); endTime.setTime( hr, start.getMinutes(), start.getSeconds()); return endTime; } } Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 22 11 Prototype: Implementazione in Java (5) Esempio di utilizzo public class PrototipeCloneExample { public static void main(String[] args) throws CloneNotSupportedException { System.out.println( "Using TimeImplementationC1:" ); CloneableTime t1 = new TimeImplementationC1(); t1.setTime( 15, 20, 10 ); CloneableTime tEnd1 = SchedulerC.calculateEnd( t1 , 6 ); System.out.println( "End: " + tEnd1.getHours() + ":" + tEnd1.getMinutes() + ":" + tEnd1.getSeconds() ); System.out.println( "Using TimeImplementationC2:" ); CloneableTime t2 = new TimeImplementationC2(); t2.setTime( 10, 15, 35 ); CloneableTime tEnd2 = SchedulerC.calculateEnd( t2 , 6 ); System.out.println( "End: " + tEnd2.getHours() + ":" + tEnd2.getMinutes() + ":" + tEnd2.getSeconds() ); Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 23 } } Abstract Factory Scopo: Fornire un’interfaccia per creare famiglie di oggetti correlati o dipendenti, senza specificarne la loro classe concreta Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 24 12 Abstract Factory (Struttura) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 25 Abstract Factory (Esempio) Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 26 13 Abstract Factory Esercizio Si pensi a un posto di vendita di sistemi Hi-Fi, dove si eseguono dimostrazioni dell’utilizzo di famiglie complete di prodotti. Specificamente si ipotizzi che esistono due famiglie di prodotti, basate su tecnologie diverse: una famiglia che ha come supporto il nastro (tape), e un’altra famiglia che ha come supporto il compact disc. In entrambi casi, ogni famiglia è composta dal supporto stesso (tape o cd), un masterizzatore (recorder) e un riproduttore (player). Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 27 AF: Applicazione del pattern Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 28 14 Abstract Factory: Implementazione in Java (1) 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 15 29 Abstract Factory: Implementazione in Java (2) Si implementano le concrete classi che costituiscono i prodotti delle famiglie. public class CD implements Media{ private String track = ""; public void writeOnDisk( String sound ) { track = sound; } public String readDisk( ) { return track; } } Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 30 15 Abstract Factory: Implementazione in Java (3) Si definisce l’abstract factory public interface DevicesFactory { public Player createPlayer(); public Recorder createRecorder(); public Media createMedia(); } Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 31 Abstract Factory: Implementazione in Java (4) Si implementano le Concrete Factories public class CDDevicesFactory implements DevicesFactory { public Player createPlayer() { return new CDPlayer(); } public Recorder createRecorder() { return new CDRecorder(); } public Media createMedia() { return new CD(); } } Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 32 16 Abstract Factory: Implementazione in Java (5) Si implementa la classe Client class Client { DevicesFactory technology; public void selectTechnology( DevicesFactory df ) { technology = df; } public void test(String song) { Media media = technology.createMedia(); Recorder recorder = technology.createRecorder(); Player player = technology.createPlayer(); recorder.accept( media ); System.out.println( "Recording the song : " + song ); recorder.record( song ); System.out.println( "Listening the record:" ); player.accept( media ); player.play(); } Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 } 33 Abstract Factory: Esempio di utilizzo Si implementa la classe Client public class AbstractFactoryExample { public static void main ( String[] arg ) { Client client = new Client(); System.out.println( “**Testing tape devices” ); client.selectTechnology( new TapeDevicesFactory() ); client.test( "I wanna hold your hand..." ); System.out.println( “**Testing CD devices” ); client.selectTechnology( new CDDevicesFactory() ); client.test( "Fly me to the moon..." ); } } Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 34 17 Sommario I Creational Design Patterns sono un insieme di patterns proposti nel catalogo GOF Essi affrontano il problema di come parametrizzare la creazione di oggetti. La categoria Creational comprende: Abstract Factory Builder Factory Method Prototype Singleton Luigi Troiano - Tecnologie di Produzione del Software: Modulo 15 35 18