Fondamenti di Informatica T2 Modulo 2 - unibo.it

Post on 26-Nov-2021

3 views 0 download

Transcript of Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

Fondamenti di Informatica T2

Modulo 2

Università degli Studi di Bologna

Facoltà di Ingegneria

Corso di Laurea in Ingegneria Informatica

Anno accademico 2008/2009

2

Veicoli

2

• Si desidera realizzare una o più classi che permettano di

modellare diverse tipologie di veicolo.

• Come per il caso della categoria concettuale animale, un

veicolo rappresenta una categoria concettuale astratta

• Non possono esistere istanze di veicolo, perché NON

ESISTE UN VEICOLO QUALSIASI

• Le istanze apparterranno invece alle sue sottoclassi

concrete

Università di Bologna – A.A. 2008/2009

3

Veicoli

3

• L’entità astratta veicolo è caratterizzata da:

– la marca, che rappresenta la casa costruttrice del

veicolo

– il modello, che rappresenta la versione di veicolo

realizzata dalla casa costruttrice

• ed è descritta tramite:

– la tipologia del veicolo

– lo scopo per cui il veicolo viene impiegato (es. trasporto

persone, trasporto merci, etc.)

– il luogo in cui si muove il veicolo (es. terra ferma, aria,

etc.)

– il mezzo tramite cui si muove il veicolo (es. ruote,

superfici alari, etc.)

4

Veicoli

4

• L’entità astratta veicolo verrà quindi modellata tramite la classe astratta Veicolo, caratterizzata da:

– metodi accessor per accedere alla marca e al modello

del veicolo

– un insieme di metodi per accedere alle stringe

descrittive del veicolo; quindi per accedere a:

• la tipologia del veicolo (tipologia)

• lo scopo per cui il veicolo viene impiegato (scopo)

• il luogo in cui si muove il veicolo (doveSiMuove)

• il mezzo tramite cui si muove il veicolo (siMuoveTramite)

– La rappresentazione a stringa di veicolo (toString)

Università di Bologna – A.A. 2008/2009

5

Veicoli

5

• La rappresentazione interna di un veicolo in termini di

marca e modello, è indipendente dallo specifico veicolo

• Una prima rappresentazione a stringa del veicolo (tramite la toString) può essere definita indipendentemente dallo

specifico veicolo, in termini della sua rappresentazione

interna e delle stringhe descrittive

6

Veicoli

6

• Le stringhe descrittive associate all’entità veicolo dipendono

dallo specifico veicolo modellato

→ è impossibile definire in Veicolo i metodi associati alle

stringhe descrittive

→ i metodi associati alle stringhe descrittive devono essere

astratti

toString utilizza i

metodi astratti!

Università di Bologna – A.A. 2008/2009

7

Veicoli

7

• Una possibile classificazione per i veicoli:

Si muove in aria

Si muove sulla terra ferma

• Non è ancora possibile definire i restanti metodi astratti

→VeicoloAereo e VeicoloTerrestre sono entrambe

classi astratte

8

Veicoli

8

• Aereo e Aliante rappresentano due possibili sottoclassi

concrete di VeicoloAereo:

Università di Bologna – A.A. 2008/2009

9

Veicoli

9

• Aereo modella l’entità veicolo aereo

– la cui tipologia è Aereo

– che si muove in aria (eredita da VeicoloAereo)

– tramite superfici alari e organo propulsore

– è adibito al trasporto di persone o merci

è possibile definire i

restanti metodi astratti!

10

Veicoli

10

Un aliante è caratterizzato anche dal numero di posti

disponibili e dalla dimensione dell’apertura

alare (espressa in metri)

vengono aggiungte nuove

informazioni rispetto algenerico veicolo

la toString di Veicolo

viene ridefinita

• Aliante modella l’entità aliante

– la cui tipologia è Aliante

– che si muove in aria (eredita da VeicoloAereo)

– tramite superfici alari, senza alcun organo propulsore

– è adibito solo al trasporto di persone

Università di Bologna – A.A. 2008/2009

11

Veicoli

11

• AereoDiLinea rappresenta una possibile specializzazione

di Aereo:

12

Veicoli

12

Un aereo di linea è caratterizzato anche dal

numero di posti disponibili

aggiunge nuove

informazioni rispetto algenerico veicolo …

• AereoDiLinea modella l’entità aereo di linea

– la cui tipologia è Aereo di Linea

– che si muove in aria (eredita da VeicoloAereo)

– tramite superfici alari e organo propulsore (eredita da Aereo)

– è adibito solo al trasporto di persone (ridefinisce scopo

definito in Aereo)

Università di Bologna – A.A. 2008/2009

13

Veicoli

13

• Autovettura e Autocarro rappresentano due possibili

sottoclassi concrete di VeicoloTerrestre:

14

Veicoli

14

• Autovettura modella l’entità autovettura

– la cui tipologia è Autovettura

– che si muove sulla superficie terrestre (eredita da VeicoloTerrestre)

– tramite ruote

– è adibita solo al trasporto di persone

Un’autovettura è caratterizzata anche dal

numero di posti disponibili

aggiunge nuove

informazioni rispetto algenerico veicolo …

Università di Bologna – A.A. 2008/2009

15

Veicoli

15

Un autocarro è caratterizzato da una capacità massima

di carico (espressa in quintali) e dal tipo di ruote

aggiunge nuove

informazioni rispetto algenerico veicolo …

• Autocarro modella l’entità autocarro

– la cui tipologia è Autocarro

– che si muove sulla terra ferma (eredita da VeicoloTerrestre)

– tramite ruote

– è adibito solo al trasporto di merce

16

Veicoli

16

• Automobile e Autobus rappresentano due possibili

specializzazioni di Autovettura:

Università di Bologna – A.A. 2008/2009

17

Veicoli

17

Un’automobile è caratterizzata anche dalnumero di porte e dal

numero di volumi

aggiunge nuove

informazioni rispetto allagenerica autovettura …

• Automobile modella l’entità automobile

– la cui tipologia è Automobile

– che si muove sulla terra ferma (eredita da VeicoloTerrestre)

– tramite ruote (eredita da Autovettura)

– è adibita solo al trasporto di un numero limitato di persone (ridefinisce scopo definito in Autovettura)

18

Veicoli

18

• Autobus modella l’entità autobus

– la cui tipologia è Autobus

– che si muove sulla terra ferma (eredita da VeicoloTerrestre)

– tramite ruote (eredita da Autovettura) ed

– adibito solo al trasporto di una collettività di persone (ridefinisce scopo definito in Autovettura)

Università di Bologna – A.A. 2008/2009

19

Veicoli

19

• Furgone rappresenta una possibile specializzazione di

Autocarro:

20

Veicoli

20

Un furgone è caratterizzata anche dal

fatto di essere finestrato o meno

aggiunge nuove

informazioni rispetto algenerico autocarro …

• Furgone modella l’entità furgone

– la cui tipologia è Furgone

– che si muove sulla terra ferma (eredita da VeicoloTerrestre)

– tramite ruote (eredita da Autocarro) ed

– adibito solo al trasporto di merce (eredita da Autocarro)

Università di Bologna – A.A. 2008/2009

21

• Si desidera avere la seguente organizzazione dei

package:

Veicoli

veicoli

Veicolo.java

Cartella

di lavoro

Test.java

Furgone.java

22

import veicoli.*;

public class Test

{

public static void main(String args[])

{

Veicolo v[] = {

new Autovettura("Mercedes-Benz", "Berlina", 4),

new Automobile("Fiat", "Panda", 5, 5, 2),

new Autobus("Mercedes-Benz", "O530 Citaro", 28),

new Furgone("Volkswagen", "Caddy", 510,

"singole", false),

new AereoDiLinea("Boeing", "707-300", 250),

new Aliante("Briegleb", "BG 12", 1, 15.24) };

22

È possibile fare ciò perché sono anche oggetti di tipo Veicolo!

Testing

Università di Bologna – A.A. 2008/2009

23

for(int i = 0; i < v.length; i++)

{

System.out.println(v[i]);

}

}

}

23

Testing

• Tramite il polimorfismo verranno richiamati i metodi definiti

dall’oggetto effettivamente referenziato. Ad esempio:

– quando viene stampato l’oggetto v[3], verrà richiamata la

toString definita per gli oggetti della classe Furgone

– la toString di v[0] richiamerà il metodo tipologia

(definito come metodo astratto nella classe Veicolo)

definito per gli oggetti della classe Autovettura

24

Soluzione - Veicoli

package veicoli;

public abstract class Veicolo

{

protected String marca;

protected String modello;

public Veicolo(String marca, String modello)

{

this.marca = marca;

this.modello = modello;

}

}

24

Università di Bologna – A.A. 2008/2009

25

Soluzione - Veicoli…

public String getMarca()

{

return marca;

}

public String getModello()

{

return modello;

}

public String toString()

{

return tipologia() + " " + marca + "/" + modello

+ ": veicolo " + scopo() + ", si muove "

+ doveSiMuove() + " tramite “

+ siMuoveTramite() + ".";

}

… 25

Metodi accessor.Metodi accessor

26

Soluzione - Veicoli

public abstract String tipologia();

public abstract String scopo();

public abstract String doveSiMuove();

public abstract String siMuoveTramite();

26

Metodi astratti

Università di Bologna – A.A. 2008/2009

27

Soluzione - Veicoli

package veicoli;

public abstract class VeicoloAereo extends Veicolo

{

public VeicoloAereo(String marca, String modello)

{

super(marca, modello);

}

public String doveSiMuove()

{

return “in aria”;

}

}

27

28

Soluzione - Veicoli

package veicoli;

public abstract class VeicoloTerrestre extends Veicolo

{

public VeicoloTerrestre(String marca, String modello)

{

super(marca, modello);

}

public String doveSiMuove()

{

return “sulla terra ferma”;

}

}

28

Università di Bologna – A.A. 2008/2009

29

Soluzione - Veicolipackage veicoli;

public class Aliante extends VeicoloAereo

{

private int numeroPosti;

private double aperturaAlare;

public Aereo(String marca, String modello, int

numeroPosti, double aperturaAlare)

{

super(marca, modello);

this.numeroPosti = numeroPosti;

this.aperturaAlare = aperturaAlare;

}

}29

30

Soluzione - Veicoli…

public int getNumeroPosti()

{

return numeroPosti;

}

public double getAperturaAlare()

{

return aperturaAlare;

}

public String tipologia()

{

return “Aliante”;

}

30

Università di Bologna – A.A. 2008/2009

31

Soluzione - Veicoli…

public String scopo()

{

return “adibito al trasporto di persone”;

}

public String siMuoveTramite()

{

return “superfici alari senza organo motopropulsore”;

}

public String toString()

{

return super.toString() + " Il veicolo ha un'apertura

alare di " + getAperturaAlare() + " metri e può

ospitare un massimo di " + getNumeroPosti()

+ (getNumeroPosti() == 1 ? " persona" : "

persone") + ".";

} 31

32

Soluzione - Veicoli

package veicoli;

public class Aereo extends VeicoloAereo

{

public Aereo(String marca, String modello)

{

super(marca, modello);

}

public String tipologia()

{

return “Aereo”;

}

}

32

Università di Bologna – A.A. 2008/2009

33

Soluzione - Veicoli

public String scopo()

{

return “adibito al trasporto di persone o merci”;

}

public String siMuoveTramite()

{

return “superfici alari e organo motopropulsore”;

}

33

34

Soluzione - Veicolipackage veicoli;

public class AereoDiLinea extends Aereo

{

private int numeroPosti;

public AereoDiLinea(String marca, String modello, int

numeroPosti)

{

super(marca, modello);

this.numeroPosti = numeroPosti;

}

public int getNumeroPosti()

{

return numeroPosti;

}

} 34

Università di Bologna – A.A. 2008/2009

35

Soluzione - Veicoli…

public String tipologia()

{

return “Aereo di linea”;

}

public String scopo()

{

return “adibito al trasporto di persone”;

}

public String toString()

{

return super.toString() + " Il veicolo può ospitare un

massimo di " + getNumeroPosti() +

(getNumeroPosti() == 1 ? " persona" : " persone")

+ ".";

}35

36

Soluzione - Veicolipackage veicoli;

public class Autovettura extends VeicoloTerrestre

{

protected int numeroPosti;

public Autovettura(String marca, String modello, int

numeroPosti)

{

super(marca, modello);

this.numeroPosti = numeroPosti;

}

public int getNumeroPosti()

{

return numeroPosti;

}

} 36

Università di Bologna – A.A. 2008/2009

37

Soluzione - Veicoli…

public String tipologia()

{

return “Autovettura”;

}

public String scopo()

{

return “adibito al trasporto di persone”;

}

public String siMuoveTramite()

{

return “ruote”;

}

37

38

Soluzione - Veicoli

public String toString()

{

return super.toString() + " Il veicolo può ospitare un

massimo di " + getNumeroPosti() +

(getNumeroPosti() == 1 ? " passeggero" : "

passeggeri")

+ ".";

}

38

Università di Bologna – A.A. 2008/2009

39

Soluzione - Veicoli

package veicoli;

public class Autocarro extends VeicoloTerrestre

{

protected double capacitàMassima;

protected String tipoRuote;

public Autocarro (String marca, String modello, double

capacitàMassima, String tipoRuote)

{

super(marca, modello);

this.capacitàMassima = capacitàMassima;

this.tipoRuote = tipoRuote;

}

}

39

40

Soluzione - Veicoli…

public String getTipoRuote()

{

return tipoRuote;

}

public double getCapacitàMassima()

{

return capacitàMassima;

}

public String tipologia()

{

return “Autocarro”;

}

40

Università di Bologna – A.A. 2008/2009

41

Soluzione - Veicoli…

public String scopo()

{

return “adibito al trasporto di merci”;

}

public String siMuoveTramite()

{

return “ruote”;

}

public String toString()

{

return super.toString() + " Il veicolo è dotato di

ruote " + getTipoRuote () + " ha una capacità

massima di " + getCapacitàMassima() +

((getCapacitàMassima() == 1) ? " quintale." :

" quintali.");

}41

42

Soluzione - Veicoli

package veicoli;

public class Automobile extends Autovettura

{

private int numeroPorte;

private int numeroVolumi;

public Automobile(String marca, String modello, int

numeroPosti, int numeroPorte, int numeroVolumi)

{

super(marca, modello, numeroPosti);

this.numeroPorte = numeroPorte;

this.numeroVolumi = numeroVolumi;

}

}42

Università di Bologna – A.A. 2008/2009

43

Soluzione - Veicoli…

public int getNumeroPorte()

{

return numeroPorte;

}

public int getNumeroVolumi()

{

return numeroVolumi;

}

public String tipologia()

{

return “Automobile”;

}

43

44

Soluzione - Veicoli…

public String scopo()

{

return “adibito al trasporto di un numero limitato di

persone”;

}

public String toString()

{

String stringaPadre = super.toString();

return stringaPadre.substring(0, stringaPadre.length()

- 1) + ", possiede " + getNumeroPorte() + "

porte, ed è a " + getNumeroVolumi()

+ ((getNumeroVolumi() == 1) ? " volume." :

" volumi.");

} 44

Università di Bologna – A.A. 2008/2009

45

Soluzione - Veicolipackage veicoli;

public class Autobus extends Autovettura

{

public Autobus(String marca, String modello, int

numeroPosti)

{

super(marca, modello, numeroPosti);

}

public String tipologia()

{

return “Autobus”;

}

public String scopo()

{

return “adibito al trasporto collettivo di persone”;

}

}45

46

Soluzione - Veicolipackage veicoli;

public class Furgone extends Autocarro

{

private boolean finestrato;

public Furgone(String marca, String modello, double

capacitàMassima, String tipoRuote, boolean finestrato)

{

super(marca, modello, capacitàMassima, tipoRuote);

this.finestrato = finestrato;

}

public boolean isFinestrato()

{

return finestrato;

}

}46

Università di Bologna – A.A. 2008/2009

47

Soluzione - Veicoli…

public String tipologia()

{

return “Furgone”;

}

public String toString()

{

String stringaPadre = super.toString();

return stringaPadre.substring(0, stringaPadre.length()

- 1) + (isFinestrato() ? " ed è" : " e non è")

+ " finestrato.";

}

47

48

import veicoli.*;

public class Test

{

public static void main(String args[])

{

Veicolo v[] = {

new Autovettura("Mercedes-Benz", "Berlina", 4),

new Automobile("Fiat", "Panda", 5, 5, 2),

new Autobus("Mercedes-Benz", "O530 Citaro", 28),

new Furgone("Volkswagen", "Caddy", 510,

"singole", false),

new AereoDiLinea("Boeing", "707-300", 250),

new Aliante("Briegleb", "BG 12", 1, 15.24) };

48

Soluzione - Veicoli

Università di Bologna – A.A. 2008/2009

49

for(int i = 0; i < v.length; i++)

{

System.out.println(v[i]);

}

}

}

49

Testing

50

Extended Phone Plan

Utilizzando i sorgenti messi a disposizione per Operator e Band, realizzare l’infrastruttura per i

piani tariffari vista in aula, in particolare:

Parte 1

1. Implementare la classe PhonePlan astratta

contenente i servizi base per tutti i PhonePlan

2. Implementare la classe PrecisePlan che realizza

l’algoritmo “preciso” di calcolo dei costi di una chiamata

3. Realizzare i test JUnit necessari alla verifica del corretto funzionamento di PrecisePlan

50

Università di Bologna – A.A. 2008/2009

51

Testing• Evitare di perdere tempo per testare Operator e Band che

sono dati

• Creare Operator e Band di test nel minimo numero

indispensabile

– Un solo Operator

– Due Band:

• Entrambe su tutti i giorni della settimana

• La prima attiva su una parte della giornata, la seconda sulla restante

parte

• Verificare il funzionamento dell’algoritmo di calcolo del

costo della chiamata nel caso in cui la chiamata sia:

– su una sola fascia oraria (un metodo di test)

– a cavallo di due fasce orarie (un altro metodo di test)

51

52

Extended Phone Plan

Parte 1 – Diagramma UML

52

class plans

Precis ePlan

+ getCallCost(Date, Date, String, String) : double

+ PrecisePlan(String, int, int, Operator[])

PhonePlan

- interval: int

- name: String

- operators: Operator ([])

- startCallCost: double

+ getCallCost(Date, Date, String, String) : double

+ getCallCost(Phon eCall) : double

+ getInterval() : int

+ getName() : String

# getOperatorByName(String) : Operator

+ getStartCallCo st() : double

+ isValid() : boolean

# PhonePlan(String, int, int, Operator[])

tlc::Operator

- bands: Band ([])

- name: String

+ getBands() : Band[]

+ getCostPerInterva l(Date) : double

+ getName() : String

+ isValid() : boolean

+ Operator(String, Band[])

- selectBandInDay(DayOfWeekEnum) : Band[]

- validateDay(DayOfWeekEnum) : boolean

tlc::Band

- combinedDays: DayOfWeekEnum ([])

- costPerInterval: double

- endTime: SimpleTime

- startTime: SimpleTime

+ Band(SimpleTime, SimpleTime, DayOfWeekEnum[], double)

+ getCombinedDays() : DayOfWeekEnum[]

+ getCostPerInterval() : double

+ getEndTime() : SimpleTime

+ getStartTime() : SimpleTime

+ isInBand(Date) : boolean

+ isValid() : boolean

+ sortByStartTime(Band[]) : void

-operators

1. .*

-bands 1. .*

Università di Bologna – A.A. 2008/2009

53

Extended Phone Plan

Parte 2

1. Implementare la classe astratta Option

2. Implementare PrecisePhonePlanWithOption

(sottoclasse di PhonePlan)

3. Realizzare i test JUnit necessari alla verifica del

corretto funzionamento di PrecisePhonePlanWithOption:

• Implementare la classe DummyOption che consenta di

verificare il funzionamento:

1. del sistema di override dei parametri del piano – verificare che

il risultato in termini di costi di una chiamata sia quello atteso

2. del sistema di notifica – verificare che il numero di notifiche

effettuate sia quello atteso

53

54

Extended Phone Plan

Parte 2 – Diagramma UML

54

class plans

PhonePlan

- interval: int

- name: String

- operators: Operator ([])

- startCallCost: double

+ getCallCost(Date, Date, String, String) : double

+ getCallCost(Phon eCall) : double

+ getInterval() : int

+ getName() : String

# getOperatorByName(String) : Operator

+ getStartCallCo st() : double

+ isValid() : boolean

# PhonePlan(String, int, int, Operator[])

PrecisePlanWithOptions

- options: Option ([])

- findApplicableOption(Date, Operator, String) : Option

+ getCallCost(Date, Date, String, String) : double

+ getOptions() : Option[]

+ getStartCallCost(Date, Op erator, String) : double

+ PrecisePlanWithOptions(String, int, int, Operator[], Option[])

Option

+ getCostPerInterval() : double

+ getInterval() : int

+ getStartCallCost() : double

+ isApplicable(Date, Operator, String) : boolean

+ notifyIntervalAccounted() : void

+ overridesCostPerInterval() : boolean

+ overridesInterval() : boolean

+ overridesStartCallCost() : boolean

-options

1. .*

Università di Bologna – A.A. 2008/2009

55

EPP - Notifiche

• Domanda

– Come si fa a conoscere il numero di notifiche effettuate all’opzione

(ovvero il numero di volte che l’opzione è stata utilizzata per

contabilizzare)?

• Risposta:

– Nel metodo che consente le notifiche inserire un contatore che deve essere visibile da fuori (getX)

– Si costruisce un nuovo piano (PrecisePhonePlanWithOptions)

passando l’opzione DummyOption di cui occorre mantenere un

riferimento

– Al termine del test verificare che il valore del contatore contenuto nella DummyOption abbia il valore atteso in base alle chiamate di

cui è stato calcolato il costo

55

56

DummyOption - Dettagli• È un’opzione di test e non è detto che debba avere pienamente

senso…

• Risponde sempre true a isApplicable

• Risponde true ai vari overrideX – avere cura di restituire valori

sensati (e semplici) nei corrispondenti metodi getX

• All’invocazione del metodo di notifica (notifyIntervalAccounted –

invocato dal piano che usa l’opzione) viene incrementato un

contatore

• Al termine del test verificare se il contatore ha raggiunto il valore

atteso ovvero se l’opzione è stata usata il numero di volte previsto

56

Università di Bologna – A.A. 2008/2009

57

EPP – Note • Notare che il testing di PrecisePhonePlanWithOptions

è indipendente dal testing delle opzioni concrete

“commerciali”

• È stato inserito in un ambiente artificiale di cui la nuova DummyOption fa parte

• Ed è stato sollecitato per verificare le attese

• Si può fare di meglio?

– Eliminare le altre dipendenze concrete (Operator) – come?

– In fase di test, utilizzare un’implementazione alternativa di Operator (più semplice) che NON coinvolga l’entità Band

57

58

Note generali sul testing

• L’oggetto/componente argomento di test dovrebbe essere

quanto più isolato possibile…

• …ed immerso in un ambiente il più artificiale possibile…

• …in modo da evitare che il funzionamento (o il NON

funzionamento) del componente stesso sia influenzato dal

funzionamento (o NON funzionamento) degli oggetti che

fanno parte del suo ambiente

58

Università di Bologna – A.A. 2008/2009

59

Note generali sul testing

• In termini di design, è necessario che una classe

abbia quante meno dipendenze concrete possibile

– per massimizzare la riusabilità – l’unità riusabile è

composta dall’oggetto più tutte le sue dipendenze

concrete)

– per facilitare il testing – l’oggetto è completamente

isolabile e può essere immerso in un ambiente

completamente artificiale: gli oggetti concreti al contorno

sono appositamente studiati solo per i test

59

60

Opzioni• Implementare l’opzione YouMeAndTheOther

– Due numeri di telefono a tariffa flat (da definire)

– Intervallo di tariffazione a 60 secondi

– Nessuno scatto alla risposta

• Implementare l’opzione FlatTime

– Mette a disposizione un certo numero di minuti “prepagati” (definibili

all’atto della costruzione)

– Intervallo di tariffazione a 30 secondi

– Nessuno scatto alla risposta

• Verificare il corretto funzionamento delle opzioni

implementate (un test JUnit per ogni classe) prima di

utilizzarle all’interno di un piano

60

Università di Bologna – A.A. 2008/2009

61

Soluzione - PhonePlanpublic abstract class PhonePlan

{

private String name;

private int interval;

private double startCallCost;

private Operator[] operators;

protected PhonePlan(String name, int interval, int

startCallCost, Operator[] operators)

{

this.name = name;

this.interval = interval; //in millisecondi

this.startCallCost = startCallCost;

this.operators = operators;

}

} 61

PhonePlan modella un piano

telefonico astratto che

definisce solo ciò che è

indipendente da una specifica

implementazione.

62

Soluzione - PhonePlan…

public String getName()

{

return name;

}

public int getInterval()

{

return interval;

}

public double getStartCallCost()

{

return startCallCost;

}

public abstract double getCallCost(Date callStart, Date

callEnd, String destOperator, String destNumber);

62

getCallCost rappresenta

l’implementazione del calcolo del

costo di una chiamata

getCallCost deve essere

definito come metodo astratto.

Università di Bologna – A.A. 2008/2009

63

Soluzione - PhonePlan…

public double getCallCost(PhoneCall call)

{

return getCallCost(call.getCallStart(),

call.getCallEnd(), call.getDestOperator(),

call.getDestNumber());

}

public boolean isValid()

{

for (Operator operator : operators)

{

if (!operator.isValid())

return false;

}

return true;

}

… 63

64

Soluzione - PhonePlan…

protected Operator getOperatorByName(String operatorName)

{

Operator selected = null;

for (Operator o : operators)

{

if (o.getName().equals(operatorName))

{

selected = o;

break;

}

}

return selected;

}

64

Università di Bologna – A.A. 2008/2009

65

Soluzione - PrecisePlanpublic class PrecisePlan extends PhonePlan

{

public PrecisePlan(String name, int interval, int

startCallCost, Operator[] operators)

{

super(name, interval, startCallCost, operators);

}

@Override

public double getCallCost(Date callStart, Date callEnd,

String destOperator, String destNumber)

{

Operator selected = getOperatorByName(destOperator);

if (selected == null)

return -1;

}

}65

PrecisePlan definisce l’algoritmo “preciso” per il calcolo

del costo di una chiamata.

66

Soluzione – PrecisePlan…

GregorianCalendar cal = new GregorianCalendar();

cal.setTime(callStart);

Date currentDateTime = cal.getTime();

double durationCost = 0;

while (currentDateTime.compareTo(callEnd) < 0)

{

durationCost +=

selected.getCostPerInterval(currentDateTime);

cal.setTime(currentDateTime);

cal.add(GregorianCalendar.MILLISECOND, getInterval());

currentDateTime = cal.getTime();

}

return getStartCallCost() + durationCost;

66

Università di Bologna – A.A. 2008/2009

67

Soluzione - PrecisePlanTestpublic class PrecisePlanTest

{

public static PrecisePlan createPlan()

{

return new PrecisePlan("TIM", 1000, 10, new Operator[]

{OperatorTest.createOperator()});

}

@Test

public void testGetCallCost()

{

PhonePlan plan = createPlan();

GregorianCalendar cal = new GregorianCalendar();

}

}67

68

Soluzione - PrecisePlanTest

cal.set(GregorianCalendar.DAY_OF_WEEK,

GregorianCalendar.WEDNESDAY);

cal.set(GregorianCalendar.HOUR_OF_DAY, 22);

cal.set(GregorianCalendar.MINUTE, 24);

cal.set(GregorianCalendar.SECOND, 0);

cal.set(GregorianCalendar.MILLISECOND, 0);

Date callStart = cal.getTime();

68

Crea l’inizio chiamata …

Università di Bologna – A.A. 2008/2009

69

Soluzione - PrecisePlanTest

cal.set(GregorianCalendar.DAY_OF_WEEK,

GregorianCalendar.WEDNESDAY);

cal.set(GregorianCalendar.HOUR_OF_DAY, 22);

cal.set(GregorianCalendar.MINUTE, 27);

cal.set(GregorianCalendar.SECOND, 0);

cal.set(GregorianCalendar.MILLISECOND, 0);

Date callEnd = cal.getTime();

double actual =

plan.getCallCost(callStart, callEnd, "TIM", "");

assertEquals(1810, actual);

}69

… crea la fine chiamataappartenente alla stessa

fascia oraria e …

… verifica che il costo della chiamata sia quello

che ci aspettiamo.

70

Soluzione - PrecisePlanTest…

@Test

public void testGetCallCost_CrossBand()

{

PhonePlan plan = createPlan();

GregorianCalendar cal = new GregorianCalendar();

cal.set(GregorianCalendar.DAY_OF_WEEK,

GregorianCalendar.WEDNESDAY);

cal.set(GregorianCalendar.HOUR_OF_DAY, 18);

cal.set(GregorianCalendar.MINUTE, 28);

cal.set(GregorianCalendar.SECOND, 0);

cal.set(GregorianCalendar.MILLISECOND, 0);

Date callStart = cal.getTime();

…70

Crea l’inizio chiamata …

Università di Bologna – A.A. 2008/2009

71

Soluzione - PrecisePlanTest

cal.set(GregorianCalendar.DAY_OF_WEEK,

GregorianCalendar.WEDNESDAY);

cal.set(GregorianCalendar.HOUR_OF_DAY, 18);

cal.set(GregorianCalendar.MINUTE, 31);

cal.set(GregorianCalendar.SECOND, 0);

cal.set(GregorianCalendar.MILLISECOND, 0);

Date callEnd = cal.getTime();

double actual = plan.getCallCost(callStart, callEnd,

"TIM", "");

assertEquals(3010, actual);

}

71

… crea la fine chiamataappartenente ad una

fascia oraria diversa e …

… verifica che il costo della chiamata sia quello

che ci aspettiamo.

72

Soluzione - PrecisePlanTest…

@Test

public void testGetCallCost_CrossBand_Dat()

{

PhonePlan plan = createPlan();

GregorianCalendar cal = new GregorianCalendar();

cal.set(GregorianCalendar.DAY_OF_WEEK,

GregorianCalendar.WEDNESDAY);

cal.set(GregorianCalendar.HOUR_OF_DAY, 23);

cal.set(GregorianCalendar.MINUTE,58);

cal.set(GregorianCalendar.SECOND, 0);

cal.set(GregorianCalendar.MILLISECOND, 0);

Date callStart = cal.getTime();

…72

Crea l’inizio chiamata …

Università di Bologna – A.A. 2008/2009

73

Soluzione - PrecisePlanTest

cal.set(GregorianCalendar.DAY_OF_WEEK,

GregorianCalendar.THURSDAY);

cal.set(GregorianCalendar.HOUR_OF_DAY, 0);

cal.set(GregorianCalendar.MINUTE, 0);

cal.set(GregorianCalendar.SECOND, 30);

cal.set(GregorianCalendar.MILLISECOND, 0);

Date callEnd = cal.getTime();

double actual = plan.getCallCost(callStart, callEnd,

"TIM", "");

assertEquals(1510, actual);

}

73

… crea la fine chiamataappartenente ad una

fascia oraria diversa e …

… verifica che il costo della chiamata sia quello

che ci aspettiamo.

74

Soluzione - Option

public abstract class Option

{

public abstract boolean isApplicable(Date istantTime,

Operator operator, String destNumber);

public abstract boolean overridesCostPerInterval();

public abstract double getCostPerInterval();

public abstract boolean overridesInterval();

public abstract int getInterval();

public abstract boolean overridesStartCallCost();

public abstract double getStartCallCost();

public abstract void notifyIntervalAccounted();

}74

Option modella un’entità che: 1) permette di ridefinire uno o

più parametri del piano tariffario; 2) può avere uno stato che cambia in base al suo utilizzo.

Università di Bologna – A.A. 2008/2009

75

Soluzione - PrecisePlanWithOptionspublic class PrecisePlanWithOptions extends PhonePlan

{

private Option[] options;

public PrecisePlanWithOptions(String name, int interval,

int startCallCost, Operator[] operators,

Option[] options)

{

super(name, interval, startCallCost, operators);

this.options = options;

}

public Option[] getOptions()

{

return options;

}

} 75

Contiene un insieme di opzioni di cui non conosce i dettegli implementativi!

PrecisePlanWithOption

modella un piano con opzioni.

76

@Override

public double getCallCost(Date callStart, Date callEnd,

String destOperator, String destNumber)

{

Operator selected = getOperatorByName(destOperator);

if (selected == null)

return -1;

GregorianCalendar cal = new GregorianCalendar();

cal.setTime(callStart);

Date currentDateTime = cal.getTime();

double startCallCost =

getStartCallCost(currentDateTime, selected,

destNumber);

}

76

Soluzione - PrecisePlanWithOptions

Università di Bologna – A.A. 2008/2009

77

double durationCost = 0;

while (currentDateTime.compareTo(callEnd) < 0)

{

Option option =

findApplicableOption(currentDateTime, selected,

destNumber);

int intervalToAdd = getInterval();

if (option != null)

{

if (option.overridesInterval())

intervalToAdd = option.getInterval();

durationCost += option.getCostPerInterval();

option.notifyIntervalAccounted();

}

… 77

Sfrutta le opzioni nel calcolo del costo di una chiamata.

Sfrutta la prima opzione applicabile nel calcolo del costo di una chiamata.

Soluzione - PrecisePlanWithOptions

78

else

{

durationCost +=

selected.getCostPerInterval(currentDateTime);

}

cal.setTime(currentDateTime);

cal.add(GregorianCalendar.MILLISECOND,

intervalToAdd);

currentDateTime = cal.getTime();

}

return startCallCost() + durationCost;

}

78

Soluzione - PrecisePlanWithOptions

Università di Bologna – A.A. 2008/2009

79

public double getStartCallCost(Date currentTime,

Operator operator, String

destNumber)

{

Option option =

findApplicableOption(currentTime, operator,

destNumber);

return (option != null &&

option.overridesStartCallCost()) ?

option.getStartCallCost() : getStartCallCost();

}

79

Soluzione - PrecisePlanWithOptions

80

private Option findApplicableOption(Date istantTime,

Operator operator, String destNumber)

{

for (Option option : options)

{

if (option.isApplicable(istantTime, operator,

destNumber))

{

return option;

}

}

return null;

}

80

Recupera la prima opzione applicabile.

Soluzione - PrecisePlanWithOptions

Università di Bologna – A.A. 2008/2009

81

Soluzione - DummyOptionpublic class DummyOption extends Option

{

private int notificationCount;

public DummyOption()

{

notificationCount = 0;

}

public int getNotificationCount()

{

return notificationCount;

}

@Override

public double getCostPerInterval()

{

return 2;

}

}81

DummyOption è una classe

realizzata per verificare il corretto funzionamento di

PrecisePhonePlaneWithOption

82

Soluzione - DummyOption…

@Override

public int getInterval()

{

return 30000;

}

@Override

public double getStartCallCost()

{

return 0;

}

@Override

public boolean isApplicable(Date istantTime,

Operator operator, String destNumber)

{

return true;

}82

Università di Bologna – A.A. 2008/2009

83

Soluzione - DummyOption

@Override

public void notifyIntervalAccounted()

{

notificationCount++;

}

@Override

public boolean overridesCostPerInterval()

{

return true;

}

83

84

Soluzione - DummyOption

@Override

public boolean overridesInterval()

{

return true;

}

@Override

public boolean overridesStartCallCost()

{

return true;

}

84

Università di Bologna – A.A. 2008/2009

85

Soluzione - PrecisePlanWOptionsTestpublic class PrecisePlanWOptionsTest

{

public static PrecisePlanWithOptions createPlan()

{

return new PrecisePlanWithOptions("TIM", 1000, 10,

new Operator[] {OperatorTest.createOperator()},

new Option[] {new DummyOption()});

}

public static PrecisePlanWithOptions createPlan(Option[]

options)

{

return new PrecisePlanWithOptions("TIM", 1000, 10,

new Operator[] {OperatorTest.createOperator()},

options);

}

} 85

86

@Test

public void testGetCallCostDateDateStringString()

{

DummyOption1 option = new DummyOption1();

PrecisePlanWithOptions plan = createPlan(new Option[]

{ option });

GregorianCalendar cal = new GregorianCalendar();

cal.set(GregorianCalendar.DAY_OF_WEEK,

GregorianCalendar.WEDNESDAY);

cal.set(GregorianCalendar.HOUR_OF_DAY, 22);

cal.set(GregorianCalendar.MINUTE, 24);

cal.set(GregorianCalendar.SECOND, 0);

cal.set(GregorianCalendar.MILLISECOND, 0);

Date callStart = cal.getTime();

…86

Soluzione - PrecisePlanWOptionsTest

Università di Bologna – A.A. 2008/2009

87

cal.set(GregorianCalendar.DAY_OF_WEEK,

GregorianCalendar.WEDNESDAY);

cal.set(GregorianCalendar.HOUR_OF_DAY, 22);

cal.set(GregorianCalendar.MINUTE, 27);

cal.set(GregorianCalendar.SECOND, 0);

cal.set(GregorianCalendar.MILLISECOND, 0);

Date callEnd = cal.getTime();

double actual = plan.getCallCost(callStart, callEnd,

"TIM", "");

assertEquals(12, actual);

assertEquals(6, option.getNotificationCount());

}

87

Soluzione - PrecisePlanWOptionsTest

Verifica il sistema di override dei parametri del piano e il sistema di

notifica.

88

@Test

public void testGetStartCallCostDateOperatorString()

{

assertEquals(0.0, createPlan().getStartCallCost(new

Date(), OperatorTest.createOperator(), “MyNumber”));

}

88

Soluzione - PrecisePlanWOptionsTest

Università di Bologna – A.A. 2008/2009

89

public class YouMeAndTheOther extends Option

{

private String destNumber1;

private String destNumber2;

private double costPerInterval;

public YouMeAndTheOther(String destNumber1,

String destNumber2, double costPerInterval)

{

this.destNumber1 = destNumber1;

this.destNumber2 = destNumber2;

this.costPerInterval = costPerInterval;

}

public boolean overridesCostPerInterval()

{

return true;

}

}89

Soluzione - YouMeAndTheOther

Permette l’override del costo relativo all’intervallo di

tariffazione.

90

@Override

public double getCostPerInterval()

{

return costPerInterval;

}

@Override

public boolean isApplicable(Date istantTime,

Operator operator, String

destNumber)

{

return destNumber.equals(destNumber1) ||

destNumber.equals(destNumber2);

}

90

Soluzione - YouMeAndTheOther

L’opzione è applicabile solo se il destinatario della chiamata è

destNumber1 o destNumber2.

Università di Bologna – A.A. 2008/2009

91

@Override

public boolean overridesInterval()

{

return true;

}

@Override

public int getInterval()

{

return 30000;

}

@Override

public boolean overridesStartCallCost()

{

return true;

}

… 91

Soluzione - YouMeAndTheOther

Permette l’override dell’intervallo di tariffazione.

Permette l’override del costo relativo allo scatto alla risposta.

92

@Override

public double getStartCallCost()

{

return 0;

}

@Override

public void notifyIntervalAccounted()

{

}

@Override

public String toString()

{

return "You, Me And The Other - " + destNumber1 + " and

"

+ destNumber2;

} 92

Soluzione - YouMeAndTheOther

Università di Bologna – A.A. 2008/2009

93

public class FlatTime extends Option

{

private int flatPeriod;

public FlatTime(int flatPeriod)

{

this.flatPeriod = flatPeriod;

}

public boolean overridesCostPerInterval()

{

return true;

}

@Override

public double getCostPerInterval()

{

return 0;

}

… 93

Soluzione - FlatTime

Permette l’override del costo relativo all’intervallo di

tariffazione.

94

@Override

public boolean isApplicable(Date istantTime,

Operator operator, String destNumber)

{

return flatPeriod >= getInterval();

}

@Override

public boolean overridesInterval()

{

return true;

}

@Override

public int getInterval()

{

return 30000;

}

… 94

Soluzione - FlatTime

Permette l’override dell’intervallo di tariffazione.

E’ applicabile solo se il numero di minuti

prepagati corrente è maggiore dell’intervallo

di tariffazione.

Università di Bologna – A.A. 2008/2009

95

@Override

public boolean overridesStartCallCost()

{

return true;

}

@Override

public double getStartCallCost()

{

return 0;

}

95

Soluzione - FlatTime

Permette l’override del costo relativo allo scatto alla risposta.

96

@Override

public void notifyIntervalAccounted()

{

flatPeriod -= getInterval();

}

@Override

public String toString()

{

return "It's a Flat Time! - Minutes left: " +

((float)flatPeriod / 60000);

}

96

Soluzione - FlatTime