1 Objektorienteret design. 2 Plan Introduktion til designmønstre Design af generiske komponenter - faktorisering - generalisering - abstrakt kobling Design.

Slides:



Advertisements
Lignende præsentationer
Den danske befolknings syn på handicappedes rettigheder
Advertisements

Atomer Et programmeret forløb. En måde at lære på.
v/ Professor Lars Ehlers, Aalborg Universitet
Program Informationer χ2-test (chi-i-anden) Projekt 3
Bolig selskabernes Landsforening– Almene lejeboliger - Maj/Juni Almene lejeboliger - Danmarkspanelet - Maj/Juni 2010.
07 – Kort om OO Introduktion.
1 Frameworks. 2 Plan Frameworks • Kollektioner • Input/output Nyt designmønster: Decorator.
T1 – OPGAVE 14.2 LINETT & SABRINA Klasse Varer namespace Opgave_14._2 { class Varer { private string vare; private string farve; private double.
Selve objektet versus referencen til objektet Nedarvning
Representations for Path Finding in Planar Environments.
Hvordan man skriver koden.
VOOP, 8 april Refleksion i objekt orienterede programmeringssprog Mandag 8/ Kasper Østerbye.
HUSKESPIL – den lille tabel
Titel: Arial, fed, skriftstr. 20, mørkegrå. Tekst: Arial, normal, fed eller kursiv, skriftstr. 10, 12 og 14 til print – 16 og 18 til projektor – mørkegrå.
Relativ vigtighed for elektroniske ressourcer,24,22,20,18,16,14,12,10 Indeks FARM nem at bruge Info om anvendelse af elektroniske.
 2 3  3 =  83  43  53  63  73  93  10 4.
GP5, Martin Lillholm 1 Grundlæggende Programmering (GP) Efterår 2005 Forelæsning 5 Slides ligger på nettet. Du er velkommen til at printe dem nu. Vi begynder.
1 UNION-FIND. 2 inddata: en følge af heltalspar (p, q); betydning: p er “forbundet med” q uddata: intet, hvis p og q er forbundet, ellers (p, q) Eksempel.
Region Midtjyllands tilbud 2013
Objektorienteret programmering
ETU 2008 | Elevtilfredshedsundersøgelse Erhvervsskolen Nordsjælland HTX (Teknisk Gymnasium) - Hillerød Baseret på 313 besvarelser.
1 Datalogi C Datastrukturer og algoritmer ved Keld Helsgaun.
1 Sortering I elementære metoder. 2 Plan Terminologi Elementære metoder til sortering -sortering ved udvælgelse -sortering ved indsættelse -Shellsort.
Forelæsning 3.1 Collections Javas for-each løkke
Matematik B 1.
Claus Brabrand, ITU, Denmark Mar 10, 2009EFFECTIVE JAVA Effective Java Presentation Workshop Claus Brabrand [ ] ( “FÅP”: First-year Project.
1 Tråde 2 Plan Trådbegrebet Synkronisering Koordinering Eksempel: et flertrådet spil.
Interfaces – brug. Overblik Tidligere: –Interfaces Comparable gør det muligt at bruge Collections metoderne –min, max, sort, … –Algoritmemønstre Find.
Grunde til at jeg elsker dig
To måder at overføre objekt- referencer mellem processer (1) Via naming service - interface RMISolver (2) Som parametre til fjernprocedurekald - interface.
Lektion 7 Læsestof: Kopier fra Caranno
Fundamentale datastrukturer
Mønstre En lille introduktion. Singleton Tilgå et objekt igennem klassereference i stedet for objektreference.  Overflødiggør referencer til objektet.
GP 8, 24/ Grundlæggende programmering Efterår 2001 Forelæsning 8 onsdag 24/ kl. 9:15 – 12:00.
Objekter og klasser Rasmus D. Lehrmann DM
1 Fundamentale datastrukturer. 2 Definitioner: abstrakt datatype, datastruktur Elementære datastrukturer og abstrakte datatyper : arrays, stakke, køer,
1 Kursusafslutning. 2 Plan Opgaveseminar Kursusevaluering.
Comparable Students German Students Composite Pattern State Pattern Observer Pattern Collections Interfaces Abstrakte klasser Design Patterns.
1 Kap. 4, Jordens Tyngdefelt = Torge, 2001, Kap. 3. Tyngdekraftens retning og størrelse g (m/s 2 ) Acceleration Tyngdepotentialet (W): evene til at udføre.
8 RÅD VEDRØRENDE GOD PROGRAMMERING Effective (brown) Java.
11 - Exceptions. 2 NOEA2009Java-kursus – Exceptions Hvad er en exception? En undtagelse. Typisk en fejl der opstår runtime Afbryder det normale programflow.
Nedarvning.
1 Implementering af fundamentale datastrukturer. 2 Stakke og køer Array-repræsentation Liste-repræsentation Hægtede lister Træer Terminologi Traversering.
Uge 14: distribuerede objekter, fjernprocedurekald, RMI Tirsdag: Introduktion Mulige fordele ved distribuerede objekter Introduktion til RMI: - Interfacets.
KF04 GRAY Item 2, 12, 22, 32, 42, 52. Consider a builder when faced with many constructor parameters Item 2.
03 – Udtryk og metoder. 2 NOEA2009Java-kursus – Udtryk og metoder Udtryk i Java Java har standard udtrykene… Værditildeling Subrutiner og funktionskald.
Hvad består en distribueret applikation af ? Processer der kører på hver deres maskine Tråde - 1 eller flere "letvægtsprocesser" per proces Objekter i.
9. Interfaces. 2 Nordjyllands Erhvervakademi Objectives “Good class design starts with good application design — how many classes, do they relate.
Blå gruppe: Søren, Alexander, Torben, Lasse. De 4 vigtige items: - Singelton - Override clone judiciously - Use interfaces only to define type - Prefer.
Begreber og Redskaber 11. Plan for idag Lidt afrunding: Collections Framework i Java Noget om oversættere og sprog Evaluering Sidste gang øvelser før.
Forelæsning 7.1 – repetition
Effective Java Blå gruppe. Item 18: Interfaces frem for abstrakte klasser Kan implementeres i klasser der ikke nedarver Eksisterende klasser kan nemt.
Begreber og Redskaber 4. Plan for idag Om metoder, parametre, returværdier Et par ord om objekt-orientering Håndkøring af programmer.
Begreber og Redskaber 3. Plan for idag Om metoder, parametre, returværdier Overblik over klasser,objekter,nedarvning Et par ord om objekt-orientering.
I o p o DAIMI, AU, November 1999Programkonstruktion I9E.1 Konstruktion og brug af klasser – en stak og en HP-regnemaskine push pop.
 Jens Bennedsen 2002Objektorienteret systemudvikling GRASP mønstre Basale ansvarsplaceringsregler.
 Jens Bennedsen 2002Objektorienteret systemudvikling Persistens.
 Henrik B. Christensen, 1999Introducerende objektorienteret programmering8B.1 Interfaces En ren kontrakt.
 Jens Bennedsen, 2003Introducerende objektorienteret programmeringinterfaces.1 Interfaces En ren kontrakt.
 Michael E. Caspersen, 2000Introducerende objektorienteret programmering6A.1 Programmering med interfaces – en stak og en HP-regnemaskine push pop.
Trinvis forfinelse Systematisk, gradvis udvikling af programmer.
Indledende Programmering Uge 6 - Efterår 2006
Interfaces Afkobling af programkomponenter (eksempel: Comparable)
Programmering med interfaces Separering af specifikation, anvendelse og implementation.
Programmering med interfaces – en stak og en HP-regnemaskine push pop.
 Jens Bennedsen 2001Multimedie programmering10B.1 Interfaces En ren kontrakt.
 Jens Bennedsen 2001Multimedie programmering4.1 Definition af begreber Interface, implements, klasse.
DAIMIIntroducerende Objektorienteret Programmering8B.1 Interfaces En ren kontrakt.
 Jens Bennedsen 2001Multimedie programmering10C.1 Brugergrænseflader Swing.
Programmering med interfaces – en stak og en HP-regnemaskine push pop.
Præsentationens transcript:

1 Objektorienteret design

2 Plan Introduktion til designmønstre Design af generiske komponenter - faktorisering - generalisering - abstrakt kobling Design case: animering af algoritmer til sortering

3 Genbrug Muligheden for genbrug af eksisterende programdele er en afgørende motivationsfaktor for at benytte objektorienteret programmering. Forudsætninger for genbrug: at finde det, man har brug for at forstå det, man har fundet at modificere det fundne, så det passer til det aktuelle behov at sammensætte det modificerede med de øvrige programkomponenter

4 Genbrug af enkeltklasser ved hjælp af nedarvning er relativt simpelt. Derimod er det svært at genbruge et objektorienteret design (en implementerings arkitektur, udtrykt ved samspillet imellem objekter og klasser). Designmønstre En designmønster er en navngiven beskrivelse af en løsning af et tilbagevendende designproblem.

5 Designmønstre sammenfatter erfaringer om programdesign i nogle få mønstre, der har vist deres værdi i praksis. Formål med designmønstre Gamma et al.: Design Patterns [1995] udgør et katalog over de 23 mest almindelige designmønstre. Formål: at understøtte genbrug af design at øge tilliden til det udviklede programmel at give designere et fælles sprog

6

7 Konstruerende mønstre (creational patterns) omhandler skabelse af objekter Strukturelle mønstre (structural patterns) omhandler den statiske sammensætning og struktur af klasser og objekter (deres relationer) Adfærdsmæssige mønstre (behavioral patterns) omhandler det dynamiske samspil imellem klasser og objekter (deres indbyrdes kommunikation) Kategorisering af designmønstre

8 Designmønstre i lærebogen Konstruerende mønstre: Singleton, Factory Factory Method Abstract Factory, Builder, Prototype Strukturelle mønstre: Composite, Decorator, Proxy Adapter Adfærdsmæssige mønstre: Template Method, Strategy, Iterator State, Command Observer Behandles Senere Ikke (læs selv kapitel 10) Senere, men er ikke med i lærebogen Nu

9 Navn Kategori Hensigt Motivation Andre navne Anvendelse Struktur Deltagere Konsekvenser Implementering Beskrivelse af designmønstre

10 Navn: Singleton Kategori: Konstruerende designmønster Hensigt: At sikre, at der kun skabes én instans af en klasse Motivation: For nogle klasser er det vigtigt, at der kun er en instans af klassen. Der skal f.eks. kun være ét filsystem og én vinduesmanager. En god løsning er, at klassen selv sikrer, at der kun skabes én instans af klassen Designmønsteret Singleton

11 Anvendelse: Anvend mønsteret, når der skal være eksakt én instans af en klasse Designmønsteret Singleton (fortsat) Deltagere: Der er kun én deltager: klassen Singleton Singleton static Singleton getInstance() operation() getData() static Singleton theInstance data return theInstance Struktur:

12 Implementering: Designmønsteret Singleton (fortsat) public class Singleton { public static Singleton getInstance() { if (theInstance == null) theInstance = new Singleton(); return theInstance; } private Singleton() { «Initialize instance fields» } «Instance fields and methods» private static Singleton theInstance = null; }

13 Forhindring af samtidig skabelse public static synchronized Singleton getInstance() Herved forhindres to (eller flere) tråde i samtidigt at generere en instans.

14 Alternative løsninger (1) (brug af undtagelse) public class Singleton { static boolean instanceCreated = false; public Singleton() throws SingletonException { if (instanceCreated) throw new SingletonException(); instanceCreated = true; «Initialize instance fields» } «Instance fields and methods» }

15 Alternative løsninger (2) (brug af klasse med statiske metoder) public final class Singleton { private Singleton() {} «Static instance fields and methods» }

16 Ved design af generiske (genbrugelige uden kodemodifikation) komponenter benyttes følgende to teknikker: (1) Faktorisering sammenfatning af fælles træk ved komponenter (2) Generalisering behandling af særtilfælde i en generel kontekst Midler: nedarvning, delegering, abstrakte klasser og grænseflader Design af generiske komponenter

17 En metode til at skabe generiske komponenter er at identificere kodesegmenter, der er ens, eller næsten ens. (1) Faktorisering (1)Identificer kodesegmenter med samme logik (2)Sammenfat denne logik i en generisk komponent (3)Omorganiser programmet, således at alle forekomster af de identificerede kodesegmenter erstattes med brug af den generiske komponent Faktorisering reducerer mængden af kode, hvilket forenkler vedligeholdelse.

18 class Computation { void method1(...) { //... computeStep1(); computeStep2(); computeStep3(); //... } void method2(...) { //... computeStep1(); computeStep2(); computeStep3(); //... } Faktorisering med metoder class FactorizedComputation { void computeAll() { computeStep1(); computeStep2(); computeStep3(); } void method1(...) { //... computeAll(); //... } void method2(...) { //... computeAll(); //... }

19 Faktorisering ved nedarvning class ComputationA { void method1(...) { //... computeStep1(); computeStep2(); computeStep3(); //... } class ComputationB { void method2(...) { //... computeStep1(); computeStep2(); computeStep3(); //... } class Common { void computeAll() { computeStep1(); computeStep2(); computeStep3(); } class ComputationA extends Common { void method1(...) { //... computeAll(); //... } class ComputationB extends Common { void method2(...) { //... computeAll(); //... }

20 Faktorisering ved delegering class Helper { void computeAll() { computeStep1(); computeStep2(); computeStep3(); } class ComputationA { void method1(...) { //... helper.computeAll(); //... } Helper helper; } class ComputationB { void method2(...) { //... helper.computeAll(); //... } Helper helper; }

21 En animeringsapplet (eksempel på faktorisering ved nedarvning) AnimationApplet start() stop() run() setDelay() getDelay() DigitalClock3 paint() Applet Runnable

22 public class AnimationApplet extends java.applet.Applet implements Runnable { public void start() { if (animationThread == null) animationThread = new Thread(this); animationThread.start(); } public void stop() { animationThread = null; } public void run() { while (animationThread != null) { repaint(); try { Thread.sleep(delay); } catch (InterruptedException e) {} } public final void setDelay(int delay) { this.delay = delay; } public final int getDelay() { return delay; } protected Thread animationThread; protected int delay = 100; }

23 import java.awt.*; import java.util.Calendar; public class DigitalClock3 extends AnimationApplet { public DigitalClock3() { setDelay(1000); } public void paint(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); g.setFont(font); g.setColor(color); g.drawString(hour + ":" + minute / 10 + minute % 10 + ":" + second / 10 + second % 10, 10, 60); } protected Font font = new Font("Monospaced", Font.BOLD, 48); protected Color color = Color.green; }

24 Hvorledes undgås flimmer? Flimmer skyldes kaldet af repaint. repaint kalder update, der som standard 1. maler hele området med baggrundsfarven, 2. sætter forgrundsfarven, og 3. kalder paint Løsning: Overskriv update Benyt et Image -objekt som buffer (mellemlager)

25 En animeringsapplet, der benytter dobbeltbuffer AnimationApplet start() stop() run() setDelay() getDdelay() DigitalClock3 paint() Applet BouncingBall initAnimator() paintFrame() DBAnimationApplet update() paint() init() initAnimator() paintFrame() Runnable

26 import java.awt.*; public abstract class DBAnimationApplet extends AnimationApplet { public final void init() { dim = getSize(); im = createImage(dim.width, dim.height); offscreen = im.getGraphics(); initAnimator(); } public final void update(Graphics g) { paintFrame(offscreen); g.drawImage(im, 0, 0, this); } public final void paint(Graphics g) { update(g); } protected void initAnimator() {} protected abstract void paintFrame(Graphics g); protected Dimension dim; protected Image im; protected Graphics offscreen; } Bemærk final -specifikationerne

27 Animering af en hoppende bold

28 import java.awt.*; public class BouncingBall extends DBAnimationApplet { protected void initAnimator() { String att = getParameter("delay"); if (att != null) setDelay(Integer.parseInt(att)); x = dim.width * 2 / 3 ; y = dim.height - radius; } protected void paintFrame(Graphics g) {... } protected int x, y; protected int dx = -2, dy = -4; protected int radius = 20; protected Color color = Color.red; } fortsættes

29 protected void paintFrame(Graphics g) { g.setColor(Color.white) g.fillRect(0, 0, dim.width, dim.height); if (x dim.width - radius) dx = -dx; if (y dim.height - radius) dy = -dy; x += dx; y += dy; g.setColor(color); g.fillOval(x - radius, y - radius, 2 * radius, 2 * radius); } (x-radius, y-radius) (x,y) dx dy

30 Maksimer fleksibilitet Sørg for at komponenterne er fleksible. Jo større fleksibilitet, desto større er chancen for genbrug. Minimer chancerne for misbrug Veldesignede klasser skal minimere mulighederne for forkert brug, og så vidt muligt afsløre eventuelle fejl på oversættelsestidspunktet. Retningslinjer for design

31 Faktorisering af fælles kodesegmenter class ContextA { void method(...) { computeStep1(); «context specific code A» computeStep2(); } abstract class Common { void method() { computeStep1(); contextSpecificCode(); computeStep2(); } abstract void contextSpecificCode(); } class ContextA extends Common { void contextSpecificCode() { «context specific code A» } class ContextB { void method(...) { computeStep1(); «context specific code B» computeStep2(); } class ContextB extends Common { void contextSpecificCode() { «context specific code B» }

32 Designmønsteret Template Method Kategori: Adfærdsmæssigt designmønster Hensigt: Definer et skelet af en algoritme i en klasses metode og overlad definitionen af nogle af skridtene til metoder i underklasser Anvendelse: For at implementere de invariante dele af en algoritme én og kun én gang og overlade det til underklasser at implementere den adfærd, der kan variere For at undgå kodeduplikering

33 Designmønsteret Template Method (fortsat) Struktur:... hookMethod1()... hookMethod2()... GenericClass templateMethod() hookMethod1() hookMethod2() ConcreteClass hookMethod1() hookMethod2()

34 Designmønsteret Template Method (fortsat) Deltagere: GenericClass (f.eks. DBAnimationApplet ), der definerer abstrakte hook- metoder (f.eks. paintFrame ), som de konkrete underklasser (f.eks. BouncingBall ) skal implementere, og en template-metode (f.eks. update ), som kalder hook-metoderne (f.eks. paintFrame ) ConcreteClass (f.eks. BouncingBall ), der implementer hook-metoderne

35 En generisk funktionsplotter (eksempel på brug af Template Method) Plotter func() paint() plotFunction() drawCoordinates() Applet PlotSine func() PlotCosine func()

36 import java.awt.*; public abstract class Plotter extends java.applet.Applet { public abstract double func(double x); public void init() { «Get the parameters and initialize the fields» } public void paint(Graphics g) { drawCoordinates(g); plotFunction(g); } protected void plotFunction(Graphics g) { «Plot the function func» } protected void drawCoordinates(Graphics g) { «Draw the x and y axes and tick marks» } Den generiske klasse

37 public class PlotSine extends Plotter { public double func(double x) { return Math.sin(x); } En konkret klasse

38 (0,0) xratio (xorigin,yorigin) yratio (x,y) xorigin : pixel x-koordinaten for (0, 0) yorigin : pixel y-koordinaten for (0, 0) xratio : antal pixels for en enhed på x-aksen yratio : antal pixels for en enhed på y-aksen

39 protected void plotFunction(Graphics g) { for (int px = 0; px < d.width; px++) { double x = (double) (px - xorigin) / xratio; double y = func(x); int py = yorigin - (int) (y * yratio); g.fillOval(px - 1, py - 1, 2, 2); } Metoden plotFunction (px-1, py-1) 2 2

40

41 (2) Generalisering Generalisering er en teknik, som tager en løsning af et specifikt problem og omformer den således, at den ikke blot kan bruges til løse dette problem, men en mængde af problemer, hvoraf det oprindelige problem blot er et særtilfælde.

42 En generisk multiplotter (eksempel på generalisering) Plotter func() paint() plotFunction() drawCoordinates() Applet MultiPlotter initMultiPlotter() init() addFuntion() plotFunction() func() Function apply() * Sine apply() Cosine apply() PlotSineCosine initMultiPlotter() creates

43 public abstract class MultiPlotter extends Plotter { abstract public void initMultiPlotter(); public final void init() { super.init(); initMultiPlotter(); } public final void addFunction(Function f, Color c) { if (f != null && numOfFunctions < MAX_FUNCTIONS) { functions[numOfFunctions] = f; colors[numOfFunctions++] = c; } protected void plotFunction(Graphics g) { «Plot the functions (calling their apply method)» } public double func(double x) { return 0.0; } protected static final int MAX_FUNCTIONS = 5; protected int numOfFunctions = 0; protected Function[] functions = new Function[MAX_FUNCTIONS]; protected Color[] colors = new Color[MAX_FUNCTIONS]; }

44 protected void plotFunction(Graphics g) { for (int i = 0; i < numOfFunctions; i++) { g.setColor(colors[i] != null ? colors[i] : Color.black); for (int px = 0; px < d.width; px++) { double x = (double) (px - xorigin) / xratio; double y = functions[i].apply(x); int py = yorigin - (int) (y * yratio); g.fillOval(px - 1, py - 1, 2, 2); } Metoden plotFunction

45 Funktioner 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); }

46 En konkret Multiplotter public class PlotSineCosine extends MultiPlotter { public void initMultiPlotter() { addFunction(new Sine(), Color.green); addFunction(new Cosine(), Color.blue); }

47

48 Designmønsteret Strategy Kategori: Adfærdsmæssigt designmønster Hensigt: Definer en familie af algoritmer, indkapsl hver af dem, og gør dem udskiftelige Anvendelse: når mange beslægtede klasser kun adskiller sig ved deres adfærd (f.eks. plotter forskellige funktioner) når der bruges forskellige udgaver af en algoritme når en klasse vælger adfærd ved hjælp af betingede sætninger når en algoritme bruger data, som klienter ikke må kende (f.eks. LayOutManager )

49 Ekesempel på anvendelse ( LayoutManager ) FlowLayout GridLayout LayoutManager Container setLayout()

50 Designmønsteret Strategy (fortsat) Struktur: StrategyA algorithm() StrategyB algorithm() Strategy algorithm() Context contextMethod() Strategy er en variant af Template Method: Ved Strategy er hook-metoderne placeret i separate klasser og kaldes ved delegering. Ved Template Method er hook-metoderne placeret i underklasser.

51 Designmønsteret Strategy (fortsat) Deltagere: Strategy (f.eks. Function ), der definerer en grænseflade, der er fælles for alle algoritmerne ConcreteStrategy (f.eks. Sine ), der implementer en algoritme, der bruger Strategy-grænsefladen Context (f.eks. MultiPlotter ), der har referencer til Strategy-objekter

52 Abstrakt kobling Abstrakt kobling: Klienter modtager service ved hjælp abstrakte klasser eller grænseflader uden at kende de aktuelle konkrete klasser. Retningslinje for design: Programmér til en grænseflade, ikke til en implementation. Herved opnås fleksible og genbrugelige løsninger.

53 Direkte kobling versus abstrakt kobling klient 1serviceudbyder A klient 3serviceudbyder C klient 2serviceudbyder B Direkte kobling klient 1 klient 3 klient 2 serviceudbyder A serviceudbyder C serviceudbyder B Standard service- protokol Abstrakt kobling

54 Abstrakte iteratorer Et eksempel på brug af abstrakt kobling En abstrakt iterator er en grænseflade, der specificerer faciliteter til sekventielt gennemløb af samlinger af objekter (f.eks. lister, tabeller og træer). interface Iterator { Object next(); boolean hasNext(); void remove(); }

55 Eksempel på implementering af en iterator interface List { Iterator iterator(); // other methods } public class LinkedList implements List { public Iterator iterator() { return new LinkedListIterator(); } private class LinkedListIterator implements Iterator { // concrete methods for the Iterator interface } // other methods and constructors }

56 Eksempel på brug List list = new LinkedList();... Iterator itr = list.iterator(); while (itr.hasNext()) System.out.println(itr.next()); Der er programmeret til grænseflader ( List og Iterator ). Klienten er derfor uberørt af de konkrete implementeringer.

57 public class LinkedList implements List { protected static class Node { Node prev, next; Object element; } protected Node first; //... } Node Object Node Object null prevnextprevnext

58 private class LinkedListIterator implements Iterator { private LinkedList.Node current; LinkedListIterator() { current = first; } public boolean hasNext() { return current != null; } public Object next() { Object obj = null; if (current != null) { obj = current.element; current = current.next; } return obj; } public void remove() { throw new UnsupportedOperationException();} }

59 Designmønsteret Iterator Kategori: Adfærdsmæssigt designmønster Hensigt: Giver en måde til sekventielt at gennemløbe en samling af objekter Anvendelse: for at tilgå indholdet i en samling objekter uden at afsløre deres interne repræsentation for at muliggøre flere samtidige gennemløb af en samling af objekter for at understøtte polymorfe gennemløb

60 Designmønsteret Iterator (fortsat) Struktur: AbstractCollection iterator() ConcreteCollection iterator() Iterator next() hasNext() ConcreteIterator next() hasNext() Return new ConcreteIterator() Creates Client

61 Designmønsteret Iterator (fortsat) Deltagere: Iterator (f.eks. Iterator ), der definerer en grænseflade for gennemløb af en samling af objekter ConcreteIterator (f.eks. LinkedListIterator ), der implementer grænsefladen og holder sig ajour med den aktuelle position i samlingen AbstractCollection (f.eks. List ), der definerer en grænseflade for skabelse af en konkret iterator (f.eks. metoden iterator) ConcreteCollection (f.eks. LinkedList ), der implementerer iterator- metoden, så den returnerer en konkret iterator

62 Grænsefladen Iterable (Java 5.0) interface Iterable { Iterator iterator(); } Hvis en klasse implementerer Iterable, kan et objekt af klassen gøres til genstand for et for/each- gennemløb: for (Obj element : list) System.out.println(element); Arrays og Javas kollektionsklasser implementerer Iterable.

63 Adskil urelaterede funktionaliteter Hvis en klasse indeholder komponenter, der tager sig af urelaterede ting, bør disse komponenter adskilles fra klassen. Minimer grænseflader Design den mindst mulige grænseflade for at minimere graden af kobling imellem komponenter. Retningslinjer for design

64 Animering af sorteringsalgoritmer (1) Sort algorithm() bubbleSort() quickSort() AlgorithmAnimator algorithm()

65 Class AlgorithmAnimator public abstract class AlgorithmAnimator extends DBAnimationApplet { // the hook method protected abstract void algorithm(); // the template method public void run() { algorithm(); } protected final void pause() { if (Thread.currentTread() == animationTread) { repaint(); try { Thread.sleep(delay); } catch (InterruptedException e) {} }

66 Class Sort public class Sort extends AlgorithmAnimator { protected void initAnimator() { String at = getParameter("alg"); algName = at != null ? at : "BubbleSort"; scramble(); } protected void algorithm() { if ("BubbleSort".equals(algName) bubbleSort(arr); else if ("QuickSort".equals(algName) quickSort(arr); } protected void paintFrame() {... } private void scramble(); { arr = new int[...];... } private void bubbleSort(int[] arr) {... } private void quickSort(int[] arr) {... } private String algName; private int arr[]; } Ufleksibel

67 Animering af sorteringsalgoritmer (2) BubbleSortAlgorithm sort() QuickSortAlgorithm sort() SortAlgorithm sort() Sort2 algorithm() AlgorithmAnimator algorithm() theAlgorithm animator Tillader dynamisk udskiftning af sorteringsalgoritme

68 Class SortAlgorithm public abstract class SortAlgorithm { abstract public void sort(int[] a); protected SortAlgorithm(AlgorithmAnimator animator) { this.animator = animator; } protected void pause() { if (animator != null) animator.pause(); } protected void swap(int[] a, int i, int j) { int temp = a[i]; a[i] = a[j]; a[j] = temp; } private AlgorithmAnimator animator; }

69 Hvor skal den konkrete instans af SortAlgorithm skabes? En mulighed er at skabe instansen i metoden initAnimator i klassen Sort2. Løsning: Indfør en klasse, hvis eneste forpligtelse er skabelse af konkrete SortAlgorithm -instanser. Ulempe: Klienten (her Sort2 ) skal kende de konkrete SortAlgorithm -klasser (de konkrete strategier), hvilket gør det vanskeligt at skifte dem ud.

70 Animering af sorteringsalgoritmer (3) (med designmønsteret Factory) SortAlgorithm sort() Sort2 algorithm() AlgorithmAnimator algorithm() theAlgorithm BubbleSortAlgorithm sort() QuickSortAlgorithm sort() animator algorithmFactory StaticAlgoFactory makeSortAlgorithm() AlgorithmFactory makeSortAlgorithm() Creates

71 interface AlgorithmFactory { SortAlgorithm makeSortAlgorithm(String algName); } Den abstrakte Factory

72 public class StaticAlgoFactory implements AlgorithmFactory { public StaticAlgoFactory(AlgorithmAnimator animator) { this.animator = animator; } public SortAlgorithm makeSortAlgorithm(String algName) { if ("BubbleSort”.equals(algName)) return new BubbleSortAlgorithm(animator); else if ("QuickSort".equals(algName)) return new QuickSortAlgorithm(animator); else return new BubbleSortAlgorithm(animator); } protected AlgorithmAnimator animator; } En konkret Factory

73 Kategori: Konstruerende designmønster Hensigt: Definer en grænseflade for skabelse af objekter og lad underklasser afgøre, hvilke klasser, der skal instantieres, og hvordan Anvendelse: når et system skal være uafhængigt af, hvorledes dets produkter skabes Designmønsteret Factory

74 Designmønsteret Factory (fortsat) Struktur: AbstractFactory makeProduct() ConcreteFactory makeProduct() Product ConcreteProduct Creates

75 Designmønsteret Factory (fortsat) Deltagere: Product (f.eks. SortAlgorithm ), der definerer en grænseflade for de objekter, som skal skabes ConcreteProduct (f.eks. QuickSortAlgorithm ), der implementer Product-grænsefladen AbstractFactory (f.eks. AlgorithmFactory ), der definerer en metode for skabelse af et Product-objekt ConcreteFactory (f.eks. StaticAlgoFactory ), der implementerer metoden til skabelse af ConcreteProduct-objekter

76 Valg af udseende Horizontal Vertical Bar Bottom

77 Animering af sorteringsalgoritmer (4) SortDisplay Sort3 Sort2 theDisplay StaticSortDisplayFactory SortDisplayFactory HSortDisplay VSortDisplay BSortDisplay BarSortDisplay Creates theDisplayFactory

78 SortDisplay interface SortDiplay { void display(int[] a, Graphics g, Dimension d); } protected void initAnimator() { String att = getParameter("dis"); theDisplayFactory = new DisplayFactory(); theDisplay = theDisplayFactory.makeSortDisplay(att); super.initAnimator(); } protected void paintFrame(Graphics g) { theDisplay.display(arr, g, getSize()); } Anvendelse i Sort3 :

79 En dynamisk Factory import java.lang.reflect.*; public class DynamicAlgoFactory implements SortAlgorithmFactory { public SortAlgorithm makeSortAlgorithm(String algName) { try { Class classForName = Class.forName(algName + "Algorithm"); Class animatorClass = animator.getClass(); Constructor constructor = null; do { try { constructor = classForName.getDeclaredConstructor( new Class[] { animatorClass }); } catch (NoSuchMethodException e) { animatorClass = animatorClass.getSuperclass(); } } while (constructor == null); return (SortAlgorithm) constructor.newInstance( new Object[] { animator }); } catch (Exception e) { throw new RuntimeException(algName + ": " + e.toString());} }

80 public class GenericFactory { public static Object getInstance(String className) { try { return Class.forName(className).newInstance(); } catch (Exception e) { throw new RuntimeException(className + ": " + e.toString()); } public static Object getInstance(String className, Object parameter) { //... } En generisk Factory fortsættes

81 public static Object getInstance(String className, Object parameter) { try { Class classForName = Class.forName(className); Class parameterClass = parameter.getClass(); Constructor constructor = null; do { try { constructor = classForName.getDeclaredConstructor( new Class[] { parameterClass }); } catch (NoSuchMethodException e) { parameterClass = parameterClass.getSuperclass(); } } while (constructor == null); return constructor.newInstance(new Object[] { parameter }); } catch (Exception e) { return null; }

82 theAlgorithm = (SortAlgorithm) GenericFactory. getInstance(algName + "Algorithm", animator); Anvendelse af den generiske Factory theDisplay = (SortDisplay) GenericFactory. getInstance(displayName + "Display");

83 Læs følgende sider i kapitel 8 i lærebogen: s og s. 366 – 395 (afsnit 8.3 overspringes). Begynd at overveje, hvad afleveringsopgaven skal omhandle. Læs vejledningen, der kan hentes via kursets hjemmeside. Løs opgaverne 7.3 og 7.5. Ugeseddel september september