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