Tecniche di Progetto (a.k.a. Design Patterns). Progettazione Object-Oriented Passi della prassi Definizione delle classi Determinazione delle responsabilità

Slides:



Advertisements
Presentazioni simili
Gestione dei Progetti Software 2 (a.a. 2004/05) - Lezione 51 Applet configurabili Grazie alla sezione parametri aggiuntivi del comando di HTML è possibile.
Advertisements

Unit à E4 Applet. Obiettivi Saper progettare e realizzare Applet Java allinterno di pagine HTML Comprendere le interazioni tra il browser e lapplet Saper.
© 2007 SEI-Società Editrice Internazionale, Apogeo Unit à B2 Gli oggetti: concetti avanzati.
Unified Modeling Language
Informatica Recupero debito quarto anno Terzo incontro.
UML: Class Diagram 1 Corso IS I /03
Differenze nei vari linguaggi di Elisa Trifirò e Barbara Tacchino
Liste di Interi Esercitazione. Liste Concatenate Tipo di dato utile per memorizzare sequenze di elementi di dimensioni variabile Definizione tipicamente.
MultiSet, Liste Ordinate
Le gerarchie di tipi.
1 Le gerarchie di tipi: implementazioni multiple e principio di sostituzione.
LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.
S.I.S.S.I.S. Catania 2002/03 LE APPLET JAVA Prof. D. Cantone Amuso Raffaele.
Elementi di programmazione grafica
Elementi di programmazione grafica
Interfacce. Interfacce come strumento di progetto Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce e riuso di codice.
Applet Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – – SIENA Uff
1 Corso di Laurea in Biotecnologie Informatica (Programmazione) Introduzione a JAVA Anno Accademico 2009/2010.
Derivazione tra classi
Overriding.
Grafico di funzione Disegna la Matematica.
1 Eventi/2 Più movimento alle classi. 2 Eventi Java Modo per intercettare il verificarsi di certe condizioni / azioni e fare in modo che venga eseguito.
Esercizi di grafica ….
Più movimento alle classi
Progettazione dei Sistemi Interattivi (a.a. 2004/05) - Lezione 81 Gestione dei colori La gestione dei colori in AWT consente di specificare un qualunque.
UML: Class Diagram Corso IS I /03
AA2003/04 © M.A. Alberti Programmazione Interfacce 1 Programmazione Corso di laurea in Informatica.
© CEFRIEL Ricettario dei principali pattern GoF Docente: Gabriele Lombardi
1 Le gerarchie di tipi. 2 Supertipi e sottotipi 4 un supertipo –class –interface 4 può avere più sottotipi –un sottotipo extends il supertipo ( class.
Progetto di applicazioni grafiche. Disegno di forme complesse Prassi : un classe per ciascuna forma Progetta la forma individuando le componenti base.
Programmazione con Interfacce
Ping Pong. PingPongComponent.java Interfaccia pubblica della componente public class PingPongComponent extends JComponent { // crea una component da includere.
1 Ereditarietà Una classe può essere derivata da una classe esistente usando la sintassi: public, protected e private specificano il tipo di accesso ai.
Java base IV: Java e la programmazione O.O.
Componenti A.Natali Marzo Oggetti u Un oggetto possiede stato, funzionamento e identita'. u Struttura e funzionamento di oggetti simili sono.
JAVA E LA GRAFICA L’architettura Java è graphics-ready
APPLICAZIONI & APPLET Java è un ottimo linguaggio per costruire applicazioni anche non per Internet anche non grafiche ma si è diffuso storicamente, e.
AlgoLab - Ereditarieta' Ereditarietà e polimorfismo in Java Laboratorio di Algoritmi 02/03 Prof. Ugo de Liguoro.
Introduzione alla programmazione Object Oriented
Enumerazioni e Classi 1. Enumerazioni Permettono di definire nuovi tipi che consistono in un insieme di valori costanti (ognuno con un nome) – Migliorano.
1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.
1 Interfacce e polimorfismo Sandro Pedrazzini Approfondimento Interfacce e polimorfismo.
1 cin>>c8 s.r.l A.A Generalità Uno dei concetti largamente adottati negli ultimi anni dai professionisti del software in fase di sviluppo.
Introduzione. Introduzione Un’applet Java: Una applet ("applicazioncina") è una applicazione non autonoma, ma pensata per far parte di una pagina Internet.
Esercitazione Ereditarietà Polimorfismo. Entita’ Geometrica PuntoCerchioPoligono TriangoloQuadrilatero Rettangolo Quadrato.
Interfacce grafiche Capitolo 27 marzo 2004 Interfacce grafiche.
Ereditarieta’. Contenuti Introduciamo un meccanismo fondamentale di Java: l’ereditarieta’ Permette di estendere classi gia’ definite (ovvero di definire.
Esercitazione su Vector. Permette di definire collezioni di dati generiche, che sono in grado di memorizzare elementi di ogni sottotipo di Object Definito.
Timer Animazioni.
Capitolo 6 Iterazione Lucidi relativi al volume: Java – Guida alla programmazione James Cohoon, Jack Davidson Copyright © The McGraw-Hill Companies.
Capitolo 12 Thread Lucidi relativi al volume: Java – Guida alla programmazione James Cohoon, Jack Davidson Copyright © The McGraw-Hill Companies.
Fondamenti di Informatica 2 Ingegneria Informatica Docente: Giovanni Macchia a.a
L.Lista, V. Innocente Design P atterns Luca Lista, Vincenzo Innocente.
Fondamenti di informatica Oggetti e Java Luca Cabibbo Luca Cabibbo – Fondamenti di informatica: Oggetti e Java Copyright © 2004 – The McGraw-Hill Companies.
Liste di Interi Esercitazione. IntList Lista di interi Una lista è una disposizione ordinata di elementi ( non in modo crescente-descrescente, ma per.
1 Gerarchie e polimorfismo: liste. 2 Generalizzare le liste di interi  List 4 lista di oggetti –non modificabile 4 vorremo poi definire un sottotipo.
Programmazione in Java. Classi I programmi in Java consistono di classi. Le classi consentono di definire: collezioni di procedure (metodi statici) tipi.
Cose nuove di Java (prima a chiacchiera, poi formalmente)
LIP: 2 Maggio 2008 Classi Astratte. Cos’e’ una Classe Astratta una classe astratta e’ un particolare tipo di classe permette di fornire una implementazione.
Ereditarieta’. Contenuti Introduciamo un meccanismo fondamentale di Java: l’ereditarieta’ Permette di estendere classi gia’ definite (ovvero di definire.
Esercitazione. Problema Vogliamo definire in modo gerachico un tipo di dato che definisce Tabelle multi-dimensionali con un numero di righe variabili.
Esercitazione sull’ ordinamento 20 maggio 2003
1 Un esempio con iteratore: le liste ordinate di interi.
LIP: 4 Maggio 2007 Interfacce. Cos’e’ una Interfaccia una interfaccia e’ un particolare tipo di classe contiene solo la specifica non ha implementazione.
Corso di Algoritmi e Strutture Dati con Laboratorio Richiami di Java – parte II.
Corso di Algoritmi e Strutture Dati con Laboratorio A.A. 2015/16 Oltre le classi.
28/12/2001package 1 Package Pacchetti e interfacce.
Introduzione all’Ereditarietà Pietro Palladino. Richiami UML Classe: descrizione di un insieme di oggetti software con caratteristiche simili Definisce.
Due slides sui Design Patterns Luciano Pandola INFN-LNGS Corso INFN su C++, ROOT e Geant4.
Transcript della presentazione:

Tecniche di Progetto (a.k.a. Design Patterns)

Progettazione Object-Oriented Passi della prassi Definizione delle classi Determinazione delle responsabilità di ciascuna classe Descrizione delle relazioni tra classi

Scoperta delle classi Classi rappresentano concetti ed entità entità concrete: conti bancari, forme geometriche, … concetti astratti: streams …

Relazioni tra classi Ereditarietà (sottotipo) Aggregazione Dipendenza

Ereditarietà Relazione is-a Stabilita tra una classe generale ed una sua specializzazione ogni savings accoung è un bank account ogni cerchio è una ellisse … Continued…

Aggregazione Relazione has-a Oggetti di una classe contengono riferimenti ad oggetti di un altra classe Ogni automobile ha una ruota (in realtà ne ha quattro … ) Da non confondere con ereditarietà

is-a vs has-a class Car extends Vehicle {... private Tire[] tires; }

Dipendenza Una relazione di uso Esempio: molte delle applicazioni che abbiamo visto dipendono dalla classe Scanner Aggregazione è una forma più forte di dipendenza

Progettazione Object-Oriented Passi della prassi Definizione delle classi Determinazione delle responsabilità di ciascuna classe Descrizione delle relazioni tra classi Obiettivi Garantire astrazione Massimizzare riuso

Progetto componenti astratte pattern: iterator Progetto di componenti riusabili/polimorfe tecniche comuni di refactoring e generalizzazione patterns: template, strategy, visitor, decorator …

Progetto di componenti astratte TIPI DI DATO: Abstract vs Concrete Lista astratta Una sequenza ordinata di elementi di un certo tipo che si possono enumerare con un iteratore Lista concreta Una sequenza di nodi che puntano ad oggetti di un certo tipo e sono collegati mendiante riferimenti

Una lista astratta

Una lista concreta

Un ListIterator astratto

Un ListIterator concreto

Pattern – Iterator ConcreteCollection iterator()... AbstractCollection iterator()... return new ConcreteIterator (this) ClientIterator next() hasNext() ConcreteIterator

Progetto di componenti polimorfe Polimorfo ~ Riutilizzabile Generics forniscono un meccanismo diretto per ottenere componenti riutilizzabili Ereditarietà e aggregazione possono essere altrettanto efficaci alcune tecniche standard codificate in design patterns

Refactoring Identificare segmenti di codice ricorrenti che realizzano la medesima logica Definire una nuova componente generica che realizza quella logica in modo univoco Ristrutturare il codice così da sostituire le ripetizioni di codice con riferimenti alla componente generica

Refactoring di una classe class Computation // Prima del refactoring { void method1(...) {... step1(); step2(); step3();... } void method2(...) {... step1(); step2(); step3();... } Continua…

Refactoring di una classe class Computation // Dopo del refactoring { void private computeAll() { step1(); step2(); step3(); } void method1(...) {... computeAll();... } void method2(...) {... computeAll();... }

Refactoring di più classi class ComputationA { void method1(...) {...; step1(); step2(); step3();...} } class ComputationB { void method2(...) {...; step1(); step2(); step3();...} } Codice duplicato su diverse classi Continua…

Refactoring di più classi Refactoring via ereditarietà class Common { void commonSteps() { step1(); step2(); step3(); } } class ComputationA extends Common { void method1(...) {... ; commonSteps();... } } class ComputationB extends Commom { void method2(...) {... ; commonSteps();... } } Continua…

Refactoring via aggregazione e delegation Refactoring di più classi class Helper { void commonSteps() { step1(); step2(); step3(); } } class ComputationA { Helper help; void method1(...) {... ; help.commonSteps();... } } class ComputationB { Helper help; void method2(...) {... ; help.commonSteps();... } }

Refactoring – UML ComputationA method1() method2() ComputationB method1() method2() Continua…

Refactoring via inheritance Refactoring – UML ComputationA method1() method2() ComputationB method1() method2() Common commonSteps() Continua…

Refactoring via aggregazione e delegation Refactoring – UML ComputationA method1() method2() ComputationB method1() method2() Helper commonSteps() helper

Una situazione più complessa class ContextA { void method(...) { ; stepA(); ; } class ContextB { void method(...) { ; stepB(); ; }

Generalizziamo la soluzione? class Common { commonCode1() { } commonCode2() { } } class ContextA extends Common { void method(...) {commonCode1(); stepA(); commonCode2();} } class ContextB { void method(...) {commonCode1(); stepB(); commonCode2();} } Continua…

Generalizziamo la soluzione? Uhm … se i due frammenti di codice comune sono strettamente dipendenti tra loro possibile che separarli generi errori rompe il flusso del controllo naturale peggiora la leggibilità del codice se i due frammenti sono parte dello stesso comando composto (ad esempio, un ciclo) non realizzabile

Esempio: due Plotters Plotter per la funzione sin(x) class PlotSin {... protected void plotFunction(Graphics g) { for (int px = 0; px < d.width; px++) { double x = (double)(px - xorigin) / (double)xratio; double y = Math.sin(x); int py = yorigin - (int) (y * yratio); g.fillOval(px - 1, py - 1, 3, 3); } Continua…

Esempio: due Plotters Plotter per la funzione cos(x) class PlotCos {... protected void plotFunction(Graphics g) { for (int px = 0; px < d.width; px++) { double x = (double)(px - xorigin) / (double)xratio; double y = Math.cos(x); int py = yorigin - (int) (y * yratio); g.fillOval(px - 1, py - 1, 3, 3); }

Una situazione più complessa class ContextA { void method(...) { ; stepA(); ; } class ContextB { void method(...) { ; stepB(); ; }

Refactoring con il pattern Template abstract class Common { void methodoTemplate (...) { ; metodoHook(...); } abstract void metodoHook(); } class ContextA extends Common { void metodoHook(...) { stepA(); } } class ContextB extends Common { void metodoHook(...) { stepB(); } }

Pattern Template classe Concreta methodHook1() methodHook2() classe Generica metodoTemplate() metodoHook1(); metodoHook2();... metodoHook1();... methdoHook2()...

Esempio: progetto di animazioni Una applicazione del pattern template Fattorizza la logica di animazione in una classe astratta Lascia la definizione dellimmagine da animare alle sottoclassi concrete Vediamo la classe astratta Animator due classi concrete BouncingBall, DigitalClock

Animator public abstract class Animator extends JComponent implements ActionListener { private int delay; private Timer T; protected Animator(int delay) { this.delay = delay; setPreferredSize(new Dimension(getWidth(),getHeight())); T = new Timer(delay, this); } // schema di animazione: guidata dagli eventi del timer public void animate(){ T.start(); } public void actionPerformed(ActionEvent event){ repaint(); } // metodo Hook public abstract void paintComponent(Graphics g); }

Domanda Perché la classe Animator è abstract ? Quale è il metodo template? Quale è il metodo hook?

Risposta E abstract perché non definisce il metodo paintComponent(), che gioca il ruolo di metodo hook in questa implementazione Il metodo template è actionPerformed() (che invoca paintComponent() via repaint() )

DigitalClock public class DigitalClock extends Animator { private Font font = new Font("Monospaced", Font.BOLD, 48); private Color color = Color.GREEN; private int width, height; public DigitalClock(int delay, int width, int height) { super(delay); this.width = width; this.height = height; }... Continua…

DigitalClock // metodo Hook public void paintComponent(Graphics g) { Calendar calendar = Calendar.getInstance(); int hour = calendar.get(Calendar.HOUR_OF_DAY); int minute = calendar.get(Calendar.MINUTE); int second = calendar.get(Calendar.SECOND); String time = + (hour / 10) + (hour % 10) + ":" + (minute / 10) + (minute % 10) + ":" + (second / 10) + (second % 10); g.setFont(font); g.setColor(color); g.drawString(time, 50, 150); } } // chiude DigitalClock

DigitalClock

BouncingBall public class BouncingBall extends Animator { // la pallina private Ellipse2D.Double ball; private final int DIAM = 30; // ampiezza dell'oscillazione private int jump; // posizione corrente private int x, y; // direzione dela prossima oscillazione 1 = dx, -1 = sx private int dir = 1; Continua…

BouncingBall // costruttore public BouncingBall(int delay, int width, int height) { super(delay); int lmargin = (int)(width * 0.1); int rmargin = (int)(width - DIAM - lmargin); jump = rmargin - lmargin; x = lmargin; y = (int)(height - DIAM) /3; ball = new Ellipse2D.Double(x,y,DIAM,DIAM); } Continua…

BouncingBall // metodo Hook public void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D)g; // calcola nuova posizione x = x + dir * jump; // inverti la direzione dir = -dir; ball.setFrame(x,y,DIAM,DIAM); g2.setColor(Color.BLUE); g2.fill(ball); } } // fine BouncingBall Continua…

BouncingBall

Esempio: progetto di un plotter Ancora applicazione del pattern template Fattorizza il comportamento grafico in una classe astratta Lascia la definizione della funzione da tracciare alle sottoclassi concrete Vediamo la classe astratta Plotter due classi concrete PlotSine, PlotCosine Continua…

Esempio: progetto di un plotter

Plotter public abstract class Plotter extends JFrame {... public Plotter(Dimension dim) {... } public void paintComponent(Graphics g) { drawCoordinates(g); plotFunction(g); } protected void drawCoordinates(Graphics g) {... }... Continua…

Plotter // metodo template protected void plotFunction(Graphics g) { for (int px = 0; px < d.width; px++) { double x = (double)(px - xorigin) / (double)xratio; double y = func(x); int py = yorigin - (int) (y * yratio); g.fillOval(px - 1, py - 1, 3, 3); } // metodo hook public abstract double func(double x); } // end Plotter

I plotter concreti Implementano il metodo hook public class PlotSine extends Plotter { public double func(double x) { return Math.sin(x); } public class PlotCosine extends Plotter { public double func(double x) { return Math.cos(x); }

Un plotter multiplo Per il momento lapplicazione assegna ad ogni plotter una sola funzione Nuova funzionalità permettere il plotting di più funzioni contemporaneamente Vincolo: ancora flessibilità: vogliamo disaccoppiare le funzioni da tracciare dal plotter stesso

Soluzione con Template public class DoublePlotter { // due metodi Hook public abstract double func1(double x); public abstract double func2(double x);... } public class TriplePlotter { // tre metodi hook public abstract double func1(double x); public abstract double func2(double x); public abstract double func3(double x);... } Continua…

Soluzione con Template ? Poco elegante: una classe plotter per ciascun numero di funzioni da tracciare Poco flessibile: dobbiamo restringerci ad un numero fissato di funzioni, mentre vorremmo definire un MultiPlotter generico Troppi poco …

Soluzione con Strategy come Template disaccoppia le funzioni da tracciare dal plotter ma invece di rappresentare ogni funzione come un metodo, rappresenta come un oggetto

Oggetti Function interface Function { double apply(double x); } public class Sine implements Function { public double apply(double x) { return Math.sin(x); } } public class Cosine implements Function { public double apply(double x) { return Math.cos(x); } } Sfruttiamo dynamic dispatch per invocare il metodo apply() corretto

Plotter Vediamo le conseguenze di questa idea nel progetto del plotter

Plotter import javax.swing.*; public abstract class Plotter extends JFrame {... private Function fun; public void paint(Graphics g) { drawCoordinates(g); plotFunction(g); } public Plotter (Dimension dim) {... }... Continua…

Plotter protected void plotFunction(Graphics g) { for (int px = 0; px < d.width; px++) { double x = (double)(px - xorigin) / (double)xratio; double y = fun.apply(x); int py = yorigin - (int) (y * yratio); g.fillOval(px - 1, py - 1, 3, 3); } } // end Plotter

Pattern Strategy StrategyyA metodoHook() Strategy metodoHook()... strategy.metodoHook();... Contesto metodoDiContesto() stragegy StrategyB metodoHook()

Pattern Strategy su Plotter Sine apply() Function apply()... fun.apply();... Plotter plotFunction() fun Cosine apply()

MultiPlotter Continua… Ora generalizziamo per creare il plotter multiplo

MultiPlotter import javax.swing.*; public abstract class MultiPlotter extends JFrame {... private List fns = new ArrayList ; private List colors = new ArrayList ; public void paint(Graphics g) { drawCoordinates(g); plotFunction(g); } public MultiPlotter (Dimension dim) {... } public void addFunction(Function f, Color c) { fns.add(f); colors.add(c); }... Continua…

MultiPlotter... protected void plotFunction(Graphics g) { for (int i = 0; i < fns.size(); i++) { if (fns.get(i) != null) { Color c = colors.tet(i); if (c != null) g.setColor(c); else g.setColor(Color.black); for (int px = 0; px < d.width; px++) { double x = (double) (px - xorigin) / (double) xratio; double y = fns.get(i).apply(x); int py = yorigin - (int) (y * yratio); g.fillOval(px - 1, py - 1, 3, 3); }}} }

Classe concreta PlotSineCosine public class PlotSineCosine extends MultiPlotter { public PlotSineCosine() { // ricordate: Sine e Cosine implementano Function addFunction(new Sine(), Color.green); addFunction(new Cosine(), Color.blue); }

Caso di studio: animazione di algoritmi La struttura di animazione generica vista negli esempi del DigitalClock e BouncingBall precedenza non è sempre adeguata Nellanimazione di un algoritmo animazione deve essere gestibile dallalgoritmo chiamata a repaint(), deve essere controllata dellesecuzione, non ad istanti stabiliti dallesterno Vogliamo comunque disaccoppiamento tra algoritmo e la struttura di animazione

Soluzione 1 – Template SortAnimator algorithm() sort() AlgorithmAninator animate() algorithm()... algorithm()... scramble() sort();... BubbleSortAnimator sort() QuickSortAnimator sort()

AlgorithmAnimator public abstract class AlgorithmAnimator extends JComponent { public AlgorithmAnimator(int d) { delay = d; } // metodi template: animate() & pause() public void animate() { algorithm(); } final protected void pause() { try { Thread.currentThread().sleep(delay); } catch (InterruptedException e) { } repaint(); } // metodi hook: paintComponent() & algorithm() abstract protected void algorithm(); private int delay; }

SortAnimator public class SortAnimator extends AlgorithmAnimator { // larray da ordinare protected int arr[]; private void swap(int a[], int i, int j) { int T; T = a[i]; a[i] = a[j]; a[j] = T; } protected void scramble() { arr = new int[getPreferredSize().height / 6]; for (int i = arr.length; --i >= 0;) { arr[i] = (int)(i * Math.random()); }

SortAnimator // metodo hook protected void paintComponent(Graphics g) { Dimension d = getSize(); g.setColor(Color.BLACK); g.fillRect(0, 0, d.width, d.height); g.setColor(Color.GREEN); int y = d.height - 10; double f = d.width / (double) arr.length; for (int i = arr.length; --i >= 0; y -= 5) { g.fillRect(0, y, (int)(arr[i] * f), 3); }

SortAnimator // metodo hook final public void algorithm() { scramble(); JOptionPane.showMessageDialog(this, "Start animation"); sort(arr); JOptionPane.showMessageDialog(this,"Done! "); } // nuovo template protected abstract void sort(int[] a); } // Chiude SortAnimator

BubbleSortAnimator public class BubbleSortAnimator extends SortAnimator { public BubbleSortAnimator(int delay) { super(delay); } // override del metodo nella superclasse protected void sort(int[] a) { for (int i = a.length; --i >= 0; ) for (int j = 0; j < i; j++) { if (a[j] > a[j+1]) swap(a, j, j + 1); pause(); }

Valutazione Implementazione molto semplice Supporta diversi algoritmi Ma … La classe SortAnimator è poco coesa fornisce metodi legati ad aspetti algoritmici e di visualizzazione Separare i due aspetti aumenta la flessibilità nuova soluzione

Soluzione 2 – Strategy SortAnimator animate() AlgorithmAninator animate() pause()... animator.pause()... sorter.sort()... BubbleSort sort() QuinckSort sort() SortingAlgorithm sort() sorter animator

AlgorithmAnimator public abstract class AlgorithmAnimator extends JComponent { private int delay; public AlgorithmAnimator(int delay){this.delay = delay;} // template degenere, no hooks public abstract void animate(); final protected void pause() { try { Thread.currentThread().sleep(delay); } catch (InterruptedException e) { } repaint(); }

SortAnimator public class SortAnimator extends AlgorithmAnimator { // larray da ordinare private int arr[]; // l'algoritmo che esegue il sorting protected SortingAlgorithm sorter; protected SortAnimator(int delay, SortingAlgorithm sorter) { super(delay); this.sorter = sorter; sorter.setAnimator(this); }

SortAnimator public void animate() { scramble(); JOptionPane.showMessageDialog(this, "Start"); sorter.sort(arr); JOptionPane.showMessageDialog(this,"Done! "); } // metodi scramble e paintComponent invariati... }

SortingAlgorithm public abstract class SortingAlgorithm { protected SortAnimator animator; public setAnimator(SortAnimator animator) { this.animator = animator; } public abstract void sort(int[] a); protected void swap(int a[], int i, int j) {... } }

BubbleSort public class BubbleSort extends SortingAlgorithm { public void sort(int[] a) { for (int i = a.length; --i >= 0; ) for (int j = 0; j < i; j++) { if (a[j] > a[j+1]) swap(a, j, j + 1); // accesso protected al // campo della superclasse animator.pause(); }

Valutazione La struttura della classe SortAnimator è migliore Ma … ci sono ulteriori misure per migliorare la coesione il metodo di visualizzazione dellarray può essere separato dallalgoritmo e dal meccanismo di animazione più flessibile

Soluzione 3 – Strategy 2 SortAnimator animate() AlgorithmAninator animate() pause() BubbleSort sort() QuinckSort sort() SortingAlgorithm sort() theDisplay DisplayMethod display() DisplayMethod display() DisplayMethod display() ConfigSortAnimator

Soluzione 3 – Strategy 2 Classi AlgorithmAnimator, Sorting Animator Gerarchia SortingAlgorithm Invariate

ConfigurableSortAnimator public class ConfigurableSortAnimator extends SortAnimator { // il visualizzatore vero e proprio protected DisplayMethod theDisplay; protected ConfigurableSortAnimator(int delay, SortingAlgorithm sorter, DisplayMethod display) { super(delay,sorter); theDisplay = display; } protected void paintComponent(Graphics g) { Dimension d = getSize(); int[] a = getArray(); theDisplay.display(a,d,g); }

DisplayMethod public interface DisplayMethod { public void display(int[] arr, Dimension d, Graphics g); } public class VDisplay implements DisplayMethod { public void display(int[] arr, Dimension d, Graphics g) {... }

Frameworks Tipicamente: insieme di classi astratte ed interfacce Forniscono applicazioni semi-complete Da specializzare Progettate cercando di garantire i principi di astrazione e di favorire il riuso mediante lapplicazione di design patterns come quelli che abbiamo visto