Föreläsning 9. Designmönstrer

Relevanta dokument
Föreläsning 9. Designmönstrer

Föreläsning 9. Designmönstrer

Target beskriver gränssnittet såsom Client vill ha det. I klassen Adapter sker konverteringen av anropen, till gränsnittet som klassen

Föreläsning 10. Designmönstrer

Faktorisering //... computeall(); //... }//method1. }//ComputationA //... //... //... computeall(); }//method1. }//ComputationA //...

Properties. Användbara metoder som kan anropas i propertychanged:

DAT043 - Föreläsning 7

Två designmönster, MVC och Observer/Observable. Objektorienterad programvaruutveckling GU (DIT011)

Designmönster/Design patterns

Subklasser och arv Inledning till grafik (JFrame och JPanel). Något om interface. Objektorienterad programvaruutveckling GU (DIT011) Subklasser

Lösningar till tentamen i EDAF25

Föreläsnings 11 - GUI, Händelsestyrda program, MVC

Programmeringsteknik II - HT18. Föreläsning 6: Grafik och händelsestyrda program med användargränssnitt (och Java-interface) Johan Öfverstedt

Detta dokument är ett exempel, cirka andra hälften av en tentamen för TDA545 Objektorienterad programvaruutveckling

Frivillig Java-swing-Graphics-lab Programmeringsteknik MN1 vt02

Lösningar till Fiktiv Tentamen på kursen. 2D4135 Objektorienterad programmering, design och analys med Java vt2004. Teoridel

Lösningar till tentamen i EDAF25

Laboration 2: Designmönster

Tentamen LÖSNINGSFÖRSLAG

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 11 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Tentamen i EDAF25. 1 juni Skrivtid: Skriv inte med färgpenna enda tillåtna färg är svart/blyerts.

Föreläsning 12. Föreläsning 12. Rörliga figurer Klassen Timer Undantag Något om applets. Rörliga appletsfigurer Klassen Timer Undantag

Design Patterns Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2017

Övning 5. TDA550 - Objektorienterad programvaruutveckling, fk

Laboration 2: Designmönster

Dagens program. Objektorienterad modellering och diskreta strukturer / design. Model/View/Control-implementering. Model/View/Control-arkitektur

Tentamen. 2D4135 vt 2005 Objektorienterad programmering, design och analys med Java Lördagen den 28 maj 2005 kl

ITK:P1 Föreläsning 4. Grafiska gränssnitt i Java. AWT-komponenter

Tentamen. DD2385 Programutvecklingsteknik vt 2013 Onsdagen den 22 maj 2013 kl Hjälpmedel: penna, suddgummi, linjal

Tentamen i Objektorienterad programmering E

DUGGA: Objektorienterade applikationer. Läs detta! Uppgifterna är inte avsiktligt ordnade efter svårighetsgrad.

Design Patterns. Objekt-orienterad programmering och design Alex Gerdes, 2016

Dagens föreläsning. Arrayer och klasser. Medan ni väntar: Gå till m.voto.se/prog11 och svara på några gamla tentamensfrågor! (26 januari 2018 F3 1 )

Observer Pattern och MVC. Objekt-orienterad programmering och design Alex Gerdes, 2016

Lösningsförslag till tentamen

Föreläsning 8 - del 2: Objektorienterad programmering - avancerat

2I1049 Föreläsning 5. Objektorientering. Objektorientering. Klasserna ordnas i en hierarki som motsvarar deras inbördes ordning

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 2 Jonas Lindgren, Institutionen för Datavetenskap, LiU

2I1049 Föreläsning 8. Grafiska gränssnitt i Java. AWT-komponenter. Grafiska gränssnitt, Java interface och händelsehantering

Lösningsförslag till tentamen i EDAF25 Objektorienterad modellering och design Helsingborg

Observer Pattern och MVC. Objekt-orienterad programmering och design (DIT953) Niklas Broberg, 2018

TDA550 Objektorienterad programvaruutveckling IT, forts. kurs Övning vecka 2

Rita Egna Bilder, Timer

Laboration 4: Game of Life

Design Patterns. En kort introduktion

Objektorienterad Programkonstruktion. Föreläsning 7 24 nov 2015

Föreläsning 3: Händelsestyrda program och användargränssnitt

Mer om grafiska komponenter. Händelsestyrda program

Tentamen i Objektorienterad programmering

Föreläsning 10. Mer om grafiska komponenter Händelsestyrda program. Layout Managers

TDDE10 m.fl. Objektorienterad programmering i Java Föreläsning 7 Erik Nilsson, Institutionen för Datavetenskap, LiU

Föreläsning 10. Mer om grafiska komponenter Händelsestyrda program. Layout Managers. Exempel: FlowLayout. Klassen FlowLayout

MVC-mönstret. model-view-control i Swing

ITK:P1 Lektion 4. Lektion 4. Lektion 4. Att implementera en spelidé i Java. DSV Peter Mozelius

Design Patterns. Objekt-orienterad programmering och design Alex Gerdes, 2018

Laborationer, moment 4 5

4.7 Observatörsmönstret

LÖSNINGSFÖRSLAG Programmeringsteknik För Ing. - Java, 5p

Lektion Händelsehanterare

Laborationer, moment 4 5

Institutionen för TENTAMEN CTH VT-15 Datavetenskap TDA550 DAG: TID: 8:30 12:30

Tentamen Programmering fortsättningskurs DIT950

Tentamen i Objektorienterad modellering och diskreta strukturer

Arv: Fordonsexempel. Arv. Arv: fordonsexempel (forts) Arv: Ett exempel. En klassdefinition class A extends B {... }

DI-institutionen Sid 1 av 6 Hans-Edy Mårtensson Sten Sundin

Interface. Interface. Tobias Wrigstad (baserat på bilder från Tom Smedsaas) 3 december 2010

F8 - Arv. ID1004 Objektorienterad programmering Fredrik Kilander

Arv. Fundamental objekt-orienterad teknik. arv i Java modifieraren protected Lägga till och modifiera metoder med hjälp av arv Klass hierarkier

UML. Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2016

Objektorienterad Programkonstruktion. Föreläsning 3 7 nov 2016

Observer Pattern och MVC. Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2017

The Last Adventure. Innehåll. Objektorientering. Språket Java. Java - Paket. Java - synlighet. Den sista lektionen. Repetition.

Tentamen LÖSNINGSFÖRSLAG

Klasshierarkier - repetition

Svaret kan ges i Javakod (eller i UML-klassdiagram). public class A { B minb;... } public class B { <B:s många variabler och metoder> } Lösning:

PROG2 Tenta Gäller SP:PROG2, DSK2:PROG2, FK:PROG2, FK:OOP, DSV1:P2 och ITK:P2

Mediator. DD2385 Programutvecklingsteknik Några bilder till föreläsning 10 6/ Designmönster: Mediator Facade State Decorator

Lycka till! TENTAMEN: Objektorienterade applikationer. Läs detta! 1 (6) Tentamen

Tentamen i Objektorienterad modellering och diskreta strukturer

Tentamen LÖSNINGSFÖRSLAG. c) Tilldelningen C x = new D() ger kompileringsfel eftersom klassen D är abstrakt.

Instuderingsuppgifter läsvecka 2

Objekt, klasser. Tillstånd Signatur Kommunikation Typ. Fält, parametrar och lokala variabler. Konstruktorer Metoder DAVA15

Kort om klasser och objekt En introduktion till GUI-programmering i Java

Projekt 2 XL. Observer-mönstret

Swing. MER Java Foundation Classes (JFC) Hur lära sig? Vad är farorna. LayoutManagers. Exempel på några av komponenterna

Föreläsning 8. Arv. Arv (forts) Arv och abstrakta klasser

Swing. MER Java Foundation Classes (JFC) Vad är farorna. Hur lära sig? LayoutManagers. Exempel på några av komponenterna

Tentamen. DD2385 Programutvecklingsteknik vt Fredagen den 5 juni 2009 kl Inga hjälpmedel utom penna, sudd och linjal

Denna vecka. Idag. Grafiskt användarsnitt. Vi kommer att se

Instuderingsuppgifter läsvecka 6 - LÖSNINGAR

12 Metaprogrammering i Java

Föreläsning 10. ADT:er och datastrukturer

Lösningsförslag: Övning 5.

Arv och polymorfi. Lite terminologi; Basklass eller superklass: En klass som fungerar som bas för vårt arv. Vi skapar nya klasser utifrån den.

Konstruktion av klasser med klasser

TENTAMEN OOP

lgammal2.txt // Lösningar till gammal tentamen // Uppgift 1 a

Objektorienterad Programkonstruktion. Föreläsning 3 9 nov 2015

Objektorienterad programutveckling, fk

Institutionen för TENTAMEN CTH VT-15 Datavetenskap TDA550 DAG: TID: 8:30 12:30

Transkript:

Föreläsning 9 Designmönstrer Faktorisering Identifiering av återkommande kodavsnitt upptäcka möjliga återanvändbara komponenter: identifiera kodavsnitt som gör samma uppgift fast på olika platser implementera denna uppgift i en återanvändbar komponent omorganisera det ursprungliga programmet. Minskar risken för inkonsistent hanterande ett eventuell fel behöver bara åtgärdas på en plats (annars behövs upprepade ändringar)

Dubblerad kod i samma klass Refactoring: Extrahera metod public class Computation { public void method1(...) { computestep1(); computestep2(); computestep3(); //method1 public void method2(...) { computestep1(); computestep2(); computestep3(); //method2 //Computation public class Computation { private void computeall(...) { computestep1(); computestep2(); computestep3(); //computeall public void method1(...) { computeall(); //method1 public void method2(...) { computeall(); //method2 //Computation Refactoring: Dubblerad kod i olika klasser public class ComputationA { public void method1(...) { computestep1(); computestep2(); computestep3(); //method1 //ComputationA public class ComputationB { public void method2(...) { computestep1(); computestep2(); computestep3(); //method2 //ComputationB public void method2( computeall(); //method2 Refactoring: Implementationsarv public abstract class Common { protected void computeall(...) { computestep1(); computestep2(); computestep3(); //computeall //Common //ComputationB public class ComputationA extends Common { public void method1(...) { computeall(); //method1 //ComputationA public class ComputationB extends Common { public void method2(...) { computeall(); //method2 //ComputationB

Dubblerad kod i olika klasser public class ComputationA { public void method1(...) { computestep1(); public class computestep2(); ComputationA { public computestep3(); void method1(...) { //method1 computestep1(); //ComputationA computestep2(); public class ComputationB { computestep3(); public void method2(...) { computestep1(); //method1 computestep2(); //ComputationA computestep3(); //method2 //ComputationB Refactoring: Delegering public class Helper { protected void computeall(...) { computestep1(); computestep2(); computestep3(); //computeall //Helper public class ComputationA { Helper helper =... ; public void method1(...) { helper.computeall(); //method1 //ComputationA public class ComputationB { Helper helper =... ; public void method2(...) { helper.computeall(); //method2 //ComputationB R public class ComputationA Helper helper =... ; public void method1(... helper.computeall(); //method1 //ComputationA plotfunction(g); // paintcomponent Dubblerad kod mixad med omgivningsberoende kod Antag att vi har en grafisk plotter för att rita ut en sinus-kurva: import java.awt.*; import javax.swing.*; public class Plotter extends JPanel{ private int xorigin; private int yorigin; private int xratio = 50; private int yratio = 50; public Plotter() { setbackground(color.white); //constructor public void paintcomponent(graphics g) { super.paintcomponent(g); drawcoordinates(g); plotfunction(g); // paintcomponent int py = yorigin g.filloval(px - 1, //plotfunction //Plotter protected void drawcoordinates(graphics g) { g.setcolor(color.black); g.drawline(0, getheight()/2, getwidth(), getheight()/2); g.drawline(getwidth()/2,0, getwidth()/2, getheight()); //drawcoordinates protected void plotfunction(graphics g) { g.setcolor(color.red); xorigin = getwidth()/2; yorigin = getheight()/2; for (int px = 0; px < getwidth(); px++) { double x = (px - xorigin) / (double) xratio; double y = Math.sin(x); int py = yorigin - (int) (y * yratio); g.filloval(px - 1, py - 1, 3, 3); //plotfunction //Plotter

Dubblerad kod mixad med omgivningsberoende kod För att rita ut en cosinus-kurva i stället för en sinus-kurva behövs endast en liten ändring i metoden plotfunction: Metoden plotfunction för sinus-kurva: protected void plotfunction(graphics g) { g.setcolor(color.red); xorigin = getwidth()/2; yorigin = getheight()/2; for (int px = 0; px < getwidth(); px++) { double x = (px - xorigin) / (double) xratio; double y = Math.sin(x); protected int py void = yorigin plotfunction(graphics - (int) (y * yratio); g) { g.filloval(px - 1, py - 1, 3, 3); g.setcolor(color.red); xorigin //plotfunction = getwidth()/2; yorigin = getheight()/2; for (int px = 0; px < getwidth(); Encapsulate what px++) varies! { double x = (px - xorigin) / (double) xratio; double y = Math.sin(x); Metoden plotfunction för cosinus-kurva: protected void plotfunction(graphics g) { g.setcolor(color.red); xorigin = getwidth()/2; yorigin = getheight()/2; for (int px = 0; px < getwidth(); px++) { double x = (px - xorigin) / (double) xratio; protected void plotf g.setcolor(color.r xorigin = getwidth yorigin = getheigh for (int px = 0; px double x = (px - double y = Math int py = yorigin g.filloval(px - 1 double y = Math.cos(x); int py = yorigin - (int) (y * yratio); g.filloval(px - 1, py - 1, 3, 3); //plotfunction Designmönstret Template Method Problem: Hur definiera en algoritm där vissa delar skiljer sig åt i olika sammanhang. Lösning: Syfte: Beskriv algoritmen i en överordnad klass som en templatemethod, som delar upp arbetet i olika deloperationer som vid behov kan omdefinieras i ärvda klasser. Definiera ett skelett av en algoritm i en metod samt skjut upp vissa steg till subklasserna. Låt subklasserna definiera dessa steg. Användbarhet: Används till att implementera invarianta delar i en algoritm, för att undvika dubblering av kod. Enheter: En superklass som implementerar skal (template) för en eller flera metoder, vilka nyttjar abstrakta metoder, s.k. hook-metoder. Konkreta klasser som implementerar hook-metoderna.

Designmönstret Template Method FrameWorkClass {abstract templatemethod() stepone() steptwo() templatemethod() {... stepone(); steptwo();... ApplicationClassB stepone() steptwo() ApplicationClassB stepone() steptwo() ApplicationClassC stepone() setptwo() Hollywood principen: Don't call us, we'll call you! protected void drawcoordinates(graphics g) { //som tidigare //drawcoordinates Refaktorering av klassen Plotter Vi skriver om klassen Plotter enligt template-mönstret: public abstract dou //Plotter import java.awt.*; import javax.swing.*; public abstract class Plotter extends JPanel{ private int xorigin; private int yorigin; private int xratio = 50; private int yratio = 50; public Plotter() { setbackground(color.white); //constructor public void paintcomponent(graphics g) { //som tidigare // paintcomponent protected void drawcoordinates(graphics g) { //som tidigare //drawcoordinates //template method protected void plotfunction(graphics g) { g.setcolor(color.red); xorigin = getwidth()/2; yorigin = getheight()/2; for (int px = 0; px < getwidth(); px++) { double x = (px - xorigin) / (double) xratio; double y = func(x); int py = yorigin - (int) (y * yratio); g.filloval(px - 1, py - 1, 3, 3); //plotfunction //hook-method public abstract double func(double x); //Plotter

Konkret plotter för sinus-funktionen För att skapa en plotter för att rita ut en sinus-funktionen behöver vi a) implementera en konkret klass där vi specificerar hook-metoden: public class PlotSine extends Plotter { public double func(double x) { return Math.sin(x); //func //PlotSine public class PlotSine extends Plotter { public double func(double x) { return Math.sin(x); b) samt en main-metod : import javax.swing.*; public class Main { //func public static void main(string[] args) { JFrame w = new JFrame(); Plotter ps = new PlotSine(); w.add(ps); w.setdefaultcloseoperation(jframe.exit_on_close); w.setsize(400,200); w.setvisible(true); //main //PlotSine import //Mainjavax.swing.*; public class Main { public static void main(string[] args) { Plotter ps = new PlotCosine(); w.add(ps); w.setdefaultcloseoperation(jframe.exit_on_close); w.setsize(400,200); w.setvisible(true); //main //Main Konkret plotter för cosinus-funktionen För att skapa en plotter för att rita ut en cosinus-funktionen behöver vi a) implementera en konkret klass där vi specificerar hook-metoden: public class PlotCosine extends Plotter { public double func(double x) { return Math.cos(x); //func //PlotCosine b) samt en main-metod : import javax.swing.*; public class Main { public static void main(string[] args) { JFrame w = new JFrame(); Plotter ps = new PlotCosine(); w.add(ps); w.setdefaultcloseoperation(jframe.exit_on_close); w.setsize(400,200); w.setvisible(true); //main //Main

Hur rita flera funktioner med samma plotter? Om vi vill rita ut två funktioner samtidig med samma plotter måste vi skapa en plotter med två hook-metoder: public abstract class TwoPlotter extends JPanel{... // template-method protected void plotfunction(graphics g) { g.setcolor(color.red); xorigin = getwidth()/2; public abstract yorigin = getheight()/2; class TwoPlotter extends JPanel{... for (int px = 0; px < getwidth(); px++) { double x = (px - xorigin) / (double) xratio; // template-method double y = funca(x); int py = yorigin - (int) (y * yratio); protected void plotfunction(graphics g) { g.filloval(px - 1, py - 1, 3, 3); g.setcolor(color.red); y = funcb(x); py = yorigin - (int) (y * yratio); //TwoPlotter xorigin = getwidth()/2; g.filloval(px - 1, py - 1, 3, 3); yorigin = getheight()/2; //plotfunction for (int px = 0; px < getwidth(); px++) { double x = (px - xorigin) / (double) xratio; double y = funca(x); // hook-methods public abstract double funca(double x); public abstract double funcb(double x); Hur rita flera funktioner med samma plotter? Om vi vill rita två funktioner samtidigt måste de konkreta klasserna implementera två hook-metoder: Om vi vill rita tre funktioner samtidigt måste de konkreta klasserna implementera tre hook-metoder: public class PlotSinCos extends TwoPlotter { public double funca(double x) { return Math.sin(x); //funca public double funcb(double x) { return Math.cos(x); //funcb //PlotSinCos public abstract class TripplePlotter {... // tre olika hook-metoder: public abstract double func1(double x); public abstract double func2(double x); public abstract double func3(double x); //TripplePlotter Strider mot Open-Closed Principle. Önskvärt att ha en MultiPlotter som ritar ut godtyckligt antal funktioner.

Designmönstret Strategy Problem: Lösning: Syfte: Användbarhet: Hur designa för att kunna välja mellan olika men relaterade algoritmer. Kapsla in de enskilda algoritmerna i en Strategy-klass. Göra algoritmerna utbytbara. när flera relaterade klasser skiljer sig endast i beteende, inte i hur de används. när algoritmerna som styr dessa beteenden använder information som klienten inte behöver känna till. när olika varianter av en algoritm behövs. Enheter: Ett interface (eller en abstrakt klass) Strategy som definierar strategin. Konkreta klasser som implementerar olika strategier. Klassen Context som handhar referenser till strategiobjekten. Designmönstret Strategy Context -strategy: Strategy contextmethod() <<interface>> Strategy algorithm() contextmethod() { strategy.algorithm(); ConcreteStrategyA algorithm() ConcreteStrategyB algorithm() ConcreteStrategyC algorithm()

MultiPlotter med användning av Strategy-mönstret Lösning: Frigör funktionen som skall ritas ut från mekanismen som ritar ut funktionen. I stället för att representera varje funktion som en metod representeras varje funktion som ett objekt. public interface Function { double apply(double x); //Function public class Sine implements Function { public double apply(double x) { return Math.sin(x); public interface Function { double apply(double x); //Function //apply //Sine public class Cosine implements Function { public double apply(double x) { return Math.cos(x); //apply //Cosine public class Sine implements Function { public double apply(double x) { return Math.sin(x); //apply //Sine Nu kan vi utnyttja dynamisk bindning i MultiPlotter genom att alltid anropa apply på objekt av olika typ (t.ex. Sine eller Cosine). abstract Multiplotter public class Cosine implements Function { import java.awt.*; import javax.swing.*; public abstract class MultiPlotter extends JPanel{ private int xorigin; private int yorigin; private int xratio; private int yratio; protected ArrayList<Function> functions = new ArrayList<Function>(); protected ArrayList<Color> colors = new ArrayList<Color>(); abstract public void initmultiplotter(); public MultiPlotter() { initmultiplotter(); setbackground(color.white); //initmultiplotter public void paintcom super.paintcompon drawcoordinates(g) plotfunctions(g); //paintcomponent public void addfunction(function f, Color c) { if (f!= null) { functions.add(f); colors.add(c); //addfunction public void paintcomponent(graphics g) { super.paintcomponent(g); drawcoordinates(g); plotfunctions(g); //paintcomponent

abstract Multiplotter protected void drawcoordinates(graphics g) { g.setcolor(color.black); g.drawline(0, getheight()/2, getwidth(), getheight()/2); protected g.drawline(getwidth()/2,0, void drawcoordinates(graphics getwidth()/2, getheight()); g) { //drawcoordinates g.setcolor(color.black); protected void plotfunctions(graphics g) { xorigin g.drawline(0, = getwidth()/2; getheight()/2, getwidth(), getheight( yorigin g.drawline(getwidth()/2,0, = getheight()/2; getwidth()/2, getheight for (int i = 0; i < functions.size(); i++) { //drawcoordinates g.setcolor(colors.get(i)); for (int px = 0; px < getwidth(); px++) { protected double x void = (px - plotfunctions(graphics xorigin) / (double) xratio; g) { xorigin double = y = getwidth()/2; functions.get(i).apply(x) apply(x); int py = yorigin - (int) (y * yratio); yorigin g.filloval(px = getheight()/2; - 1, py - 1, 3, 3); for (int i = 0; i < functions.size(); i++) { //plotfunctions g.setcolor(colors.get(i)); for (int px = 0; px < getwidth(); px++) { double x = (px - xorigin) / (double) xratio; double y = functions.get(i).apply(x) apply(x); //MultiPlotter Två konkreta MultiPlotters import java.awt.color; public class DoublePlotter extends MultiPlotter { public void initmultiplotter() { addfunction(new Sine(), Color.GREEN); addfunction(new Cosine(), Color.BLUE); //initmultiplotter //DoublePlotter addfunction(new Cosine addfunction(new Atan() //initmultiplotter //TripplePlotter import java.awt.color; public class TrippelPlotter extends MultiPlotter { public void initmultiplotter() { addfunction(new Sine(), Color.GREEN); addfunction(new Cosine(), Color.BLUE); addfunction(new Atan(), Color.RED); //initmultiplotter //TripplePlotter

Designmönstret Singleton En singleton-klass är en klass som det får finnas endast en instans av och denna instans är globalt åtkomlig. Singleton -instance: Singleton -Singleton() +getinstance(): Singleton... Den globala instansen av klassen hålls som en privat klassvariabel i klassen själv (variabeln instance i figuren ovan). Konstruktorn i klassen är privat! Användare erhåller instansen av klassen via metoden getinstance(). En singleton klass är i övrigt som en vanlig klass och kan självklart ha fler variabler och metoder. Designmönstret Singleton public class Singleton { private static final Singleton instance = new Singleton(); // Other useful instance variables here private Singleton() { public static Singleton getinstance() { return instance; //getinstance() // Other useful methods here //Singleton Statiska attribut i en klass initieras när Javas Viritual Machine laddar in klassen. Eftersom en klassen måste finnas inladdad innan någon av dess metoder anropas kommer alltså attributet instance att initieras innan metoden getinstance anropas första gången.

Designmönstret Singleton Instansieringen kan skjutas upp tills metoden getinstance anropas för första gången. Detta innebär att denna metod måste göras trådsäker (konstruktionen synchronized). public class LazySingleton { private static LazySingleton instance; // Other useful instance variables here private LazySingleton() { public static synchronized LazySingleton getinstance() { public if (instance class == LazySingleton null) { { instance = new LazySingleton(); private static instance; // Other return instance; useful instance variables here //getinstance() private // Other useful LazySingleton() methods here { //LazySingleton public static synchronized LazySingleton getinstance if (instance == null) { instance = new LazySingleton(); Vi återkommer till trådsäkerhet i en senare föreläsning Designmönstret Adapter Designmönstret Adapter Pattern konverterar gränsnittet hos en klass till ett annat gränssnitt så att inkomplatibla klasser kan samarbeta. Client <<interface>> Target +request(): void Adapter +request(): void Adaptee +otherrequest(): void... adaptee.otherrequest();... Target beskriver gränssnittet såsom Client vill ha det. I klassen Adapter sker konverteringen av anropen, till gränsnittet som klassen Adaptee tillhandahåller

Designmönstret Adapter public interface SquarePeg { public void insert(string str); //SquarePeg public class ConcreteSquarePeg implements SquarePeg{ public void insert(string str) { System.out.println("SquarePeg insert: " + str); //insert //ConcreteSquarePeg public class RoundPeg { public void insertintohole(string msg) { System.out.println("RoundPeg insertintohole: " + msg); //InsertIntoHole //RoundPeg Designmönstret Adapter public class PegAdapter implements SquarePeg { private RoundPeg roundpeg; public PegAdapter(RoundPeg peg) { this.roundpeg = peg; //constructor public void insert(string str) { roundpeg.insertintohole(str); //insert //PegAdapter Utskrift: SquarePeg insert: Inserting square peg! RoundPeg insertintohole: Inserting round peg! public class TestPegs { public static void main(string[] args) { RoundPeg roundpeg = new RoundPeg(); SquarePeg squarepeg = new ConcreteSquarePeg(); SquarePeg adapter = new PegAdapter(roundPeg); squarepeg.insert("inserting square peg!"); adapter.insert("inserting round peg!"); //main //TestPegs

Designmönstret Factory Method Factory method används när man vid exekveringen måste avgöra vilken typ av objekt som skall skapas vill undvika beroenden av konkreta klasser. Client <<interface>> Creator +factorymethod() <<interface>> Product ConcreteProductA ConcreteProductB ConcreteCreatorA +factorymethod() ConcreteCreatorB +factorymethod() Designmönstret Factory Method public class DefaultProduct implements Produ public String shipfrom () { return " not available"; Produkter public interface Product { abstract public String shipfrom(); public class ProductA implements Product { public String shipfrom () { return " from South Africa"; public class ProductB implements Product { public String shipfrom () { return " from Spain"; public class ProductC implements Product { public String shipfrom () { return " from Mexico"; public class DefaultProduct implements Product { public String shipfrom () { return " not available";

Designmönstret Factory Method Fabriker public interface Creator { abstract public Product factorymethod(int month); public class ConcreteCreatorA implements Creator { public Product factorymethod(int month) { public interface if (month >= Creator 4 && month { <=11) return new ProductA(); abstract else public if (month == 1 month factorymethod(int == 2 month == 12) month); return new ProductB(); else public return class new ConcreteCreatorA DefaultProduct(); implements Creator { public Product factorymethod(int month) { public class ConcreteCreatorB implements Creator { if (month >= 4 && month Klient <=11) public Product factorymethod(int month) { return new new ProductC(); ProductA(); else if (month == 1 month == 2 month == 12) return new ProductB(); else return new DefaultProduct(); Designmönstret Factory Method Client public class Main { public static void main(string[] args) { Creator c = new ConcreteCreatorA(); System.out.println("From ConcreteCreatorA:"); printyearlydeliver(c); c = new ConcreteCreatorB(); System.out.println("From ConcreteCreatorB:"); printyearlydeliver(c); private static void printyearlydeliver(creator c) { for (int i = 1; i <= 12; i++) { Product product = c.factorymethod(i); System.out.println("Avocados " + product.shipfrom()); Körningsexempel: From ConcreteCreatorA: Avocados from Spain Avocados from Spain Avocados not available Avocados from South Africa Avocados from South Africa Avocados from South Africa Avocados from South Africa Avocados from South Africa Avocados from South Africa Avocados from South Africa Avocados from South Africa Avocados from Spain From ConcreteCreatorB: Avocados from Mexico Avocados from Mexico Avocados from Mexico Avocados from Mexico Avocados from Mexico Avocados from Mexico Avocados from Mexico Avocados from Mexico Avocados from Mexico Avocados from Mexico Avocados from Mexico Avocados from Mexico

Designmönstret Decorator Designmönstret Decorator används för att lägga till funktionalitet på individuella objekt utan att använda arv. Mönstret används ofta då arv skulle ge alldeles för många nivåer i arvshierarkin, eller då arv inte är möjligt. Rekommenderad struktur för Decorator-mönstret är enligt: Component {abstract operation() Component: En klass som definierar gränssnittet för de objekt som dynamiskt kan ges ytterligare funktionalitet. ConcreteComponent operation() Decorator {abstract operation() ConcreteComponent: En klass som definierar objekt till vilka ytterligare funktionalitet kan ges. super.operation() addedbehavior() ConcreteDecoratorB operation() addedbehavior() ConcreteDecoratorA addedstate operation() Decorator: Har en referens till ett Component-objekt och definierar ett gränssnitt som överensstämmer med gränssnittet för Component. ConcreteDecorator: Lägger till funktionalitet på objektet. Exempel på användning av Decorator Antag att vi har en smörgåsbutik. Kunden kan kombinera sin smörgås efter eget önskemål. Det finns ett antal brödsorter att välja mellan och ett antal olika pålägg. Vi startar med att skapa en abstrakt klass Sandwich enligt: abstract public class Sandwich { protected String name; public String getname() { return name; //getname abstract public double getprice(); //Sandwich

Exempel på användning av Decorator Sedan skapar vi en klass för var och en av de brödsorter vi har. Dessa klasser ärver klassen Sandwich. Säg att vi har panini och baguetter: public class Panini extends Sandwich { public Panini(){ name = "Panini"; //constructor public double getprice() { return 10.5; //getprice //Panini public class Baguette extends Sandwich { public Baguette() { name = "Baguette"; //constructor public double getprice() { return 8.5; //getprice //Baguette Exempel på användning av Decorator Sedan inför vi vår Decorator-klass, SandwichDecorator, vilken är en abstrakt klass som ärver från Sandwich-klassen och som har en instansvariabel av klassen Sandwich: abstract public class SandwichDecorator extends Sandwich { protected Sandwich decoratedsandwich; public abstract double getprice(); //SandwichDecorator Nu kan vi skapa konkreta klasser, t.ex. för att lägga ost, skinka, salami eller tomater på smörgåsen.

Exempel på användning av Decorator Nu kan vi skapa konkreta klasser, t.ex. för att lägga ost, skinka, salami eller tomater på smörgåsen: public class Cheese extends SandwichDecorator { public Cheese (Sandwich sandwich) { decoratedsandwich = sandwich; name = decoratedsandwich.name + " + Cheese"; //constructor private double chargecheese() { return 5.5; public double getprice() { return decoratedsandwich.getprice() + chargecheese(); //getprice //Cheese public class Ham extends SandwichDecorator { public Ham (Sandwich sandwich) { decoratedsandwich = sandwich; name = decoratedsandwich.name + " + Ham"; //constructor private double chargeham() { return 7.5; public double getprice() { return decoratedsandwich.getprice() + chargeham(); //getprice //Ham Exempel på användning av Decorator public class Salami extends SandwichDecorator { public Salami (Sandwich sandwich) { decoratedsandwich = sandwich; name = decoratedsandwich.name + " + Salami"; //constructor private double chargesalami() { return 8.5; public double getprice(){ return decoratedsandwich.getprice() + chargesalami(); //getprice //Salami public class Tomato extends SandwichDecorator { public Tomato (Sandwich sandwich) { decoratedsandwich = sandwich; name = decoratedsandwich.name + " + Tomato"; //constructor private double chargetomato() { return 2.5; public double getprice(){ return decoratedsandwich.getprice() + chargetomato(); //getprice //Tomato

Exempel på användning av Decorator Sandwich {abstract getprice() Baguette getprice(() Panini getprice(() SandwichDecorator {abstract getprice() Salami getprice() Ham getprice() Cheese getprice() Tomato getprice() Exempel på användning av Decorator public class TestSandwich { public static void main (String[] args){ //lets create a baguette with cheese, ham and tomato Sandwich ourbaguette= new Baguette(); ourbaguette = new Cheese(ourBaguette); ourbaguette = new Ham(ourBaguette); ourbaguette = new Tomato(ourBaguette); System.out.println(ourBaguette.getName() + " = " + ourbaguette.getprice() + " kronor"); //lets create a panini with salami and tomato. Sandwich ourpanini = new Panini(); ourpanini = new Salami(ourPanini); ourpanini = new Tomato(ourPanini); System.out.println(ourPanini.getName() + " = " + ourpanini.getprice() + " kronor"); //main //TestSandwich När programmet körs erhålls utskriften: Baguette + Cheese + Ham + Tomato = 24.0 kronor Panini + Salami + Tomato = 21.5 kronor

Designmönstret Observer Designmönstret Observer är en teknik som tillåter ett objekt som ändrat sitt tillstånd att rapportera detta till andra berörda objekt så att de kan vidta lämpliga åtgärder. Designmönstret Observer definierar en-till-många relation minskar kopplingen mellan objekt Java stöder designmönstret Observer genom: klassen Observable och interfacet Observer klassen PropertyChangeSupport och interfacet PropertyChangeListener Designmönstret Observer Observable +addobserver(o : Observer): void +deleteobserver(o :Observer): void #setchanged(): void +notifyobservers(): void <<interface>> Observer +update(o : Observable; arg: Object):void Publisher +modifystate(): void +getvalue(): Value ConcreteObserver +update(o: Observable; arg: Object): void Det objekt som tillkännager att det ändrat sitt tillstånd är alltså observerbart (observable) och kallas ofta publisher. De objekt som underrättas om tillståndsförändringen kallas vanligtvis observers eller subscribers. Ovanstående klassdigarm överensstämmer med interfacet Observer och klassen Observable i Java.

Designmönstret Observer Klassen Observable i Java har bl.a följande metoder: void addobserver(observer o) lägger till en ny observatör o. void deleteobserver(observer o) tar bort observatören o. void notifyobservers() protected void setchanged() meddelar alla observatörer att tillståndet har förändrats. markerar att tillståndet har ändrats. Måste anropas för att notifyobservers() verkligen kommer att meddela observatörerna. Interfacet Observer i Java har metoden void update(observable o, Object arg) som anropas av det observerbara objektet o när detta har förändrats. Designmönstret Observer :Publisher :ConcreteObserverA :ConcreteObserverB addobserver(this) addobserver(this) modifystate() notifyobservers() update(this, obj) getvalue() update(this, obj) getvalue()

Exempel Datorintrång import java.util.observable; public class IntrusionDetector extends Observable { public void someonetriestobreakin() { //Denna metod anropas när någon försöker hacka sig in // i datorn. Detta meddelas alla som är intresserade setchanged(); notifyobservers(); //someonetriestobreakin //IntrusionDetector import java.util.observer; import java.util.observable; public class SysAdm implements Observer{ private String name; private IntrusionDetector dectector; public SysAdm( String name, IntrusionDetector dectector) { this.name = name; this.dectector = dectector; //constructor public void subscribe( ) { dectector.addobserver(this); //subscriber public void update(observable server, Object err ) { System.out.println( name + " got the message!" ); //update //SysAdm Exempel Datorintrång public class Main { public static void main( String[] argv ) { IntrusionDetector id = new IntrusionDetector(); SysAdm kalle = new SysAdm( "Kalle", id ); SysAdm sven = new SysAdm( "Sven", id ); SysAdm rune = new SysAdm( "Rune", id ); kalle.subscribe(); rune.subscribe(); // Nu låtsas vi att någon försöker ta sig in id.someonetriestobreakin(); //main //Main Rune got the message! Kalle got the message!

Designmönstret State Objekt har tillstånd och beteenden. Objekt ändrar sina tillstånd beroende på interna och externa händelser. Om ett objekt går igenom ett antal klart identifierbara tillstånd och objektets beteende påverkas signifikant av sitt tillstånd kan det vara lämpligt att använda designmönstret State. //state-dependet method //delegate to concrete state public void method1() { state.operation1(); public void method2() { state.operation2(); Context -state: State method1() method2() <<interface>> State operation1() operation2() ConcreteState1 operation1() operation2() ConcreteState2 operation1() operation2() ConcreteState3 operation1() operation2() Designmönstret State State-mönstret kapslar in de individuella tillstånden tillsammans med den logik som används för att byta tillstånd. Istället för att direkt implementera beteendet för ett objekt i metoderna i klassen, så delegerar objektet vidare vad som skall göras till ett annat objekt (som är av en annan klass). Detta innebär att man dynamiskt kan konfigurera om och byta ut beteendet hos objekt, det är som att objektet "byter klass". Vanligt arv är ju en statisk relation som inte kan förändras under runtime. Designmönstret State har samma strukturell uppbyggnad som designmönstret Strategy, men har ett annat syfte.

Exempel på State-mönstret Antag att vi har en amfibiebil. När amfibiebilen körs på land driver motorn bakhjulen och när den körs i vatten driver motorn två propellrar. Styrningen sker både på land och i vatten med framhjulen. Låt oss säga vi vill ha följande operationer på amfibiebilen: prepareforwater() prepareforland() turnright() turnleft() go() stop() byt tillstånd för att köras i vatten byt tillstånd för att köras på land sväng höger, samma både på land och i vatten sväng vänster, samma både på land och i vatten kör, är olika beroende av om amfibiebilen är på land eller i vatten stanna, är olika beroende av om amfibiebilen är på land eller i vatten Design //state-dependent method //delegate to concrete state public void go() { state.moveforward(); //change state public void prepareforland() { state = car; Amphicar -state: Conveyance -car: Conveyance -boat: Conveyance +go() +stop() +turnleft() +turnright( +prepareforwater() +prepareforland() <<interface>> Conveyance +moveforward() +slowdown() Car +moveforward() +slowdown() Boat +moveforward() +slowdown()

Interfacet Conveyance och klasserna Car och Boat public interface Conveyance { abstract public void moveforward(); abstract public void slowdown(); //Conveyance public class Car implements Conveyance { public Car(){; public void moveforward() { System.out.println( "Forward power to rear wheels"); //moveforward public void slowdown() { public interface Conveyance { abstract public void moveforward(); abstract public void slowdown(); //Conveyance ublic class System.out.println( Car implements Conveyance { public Car(){; "Apply breaks on each wheel"); //slowdown public //Carvoid moveforward() { System.out.println( "Forward power to rear wheels"); //moveforward public void slowdown() { public class Boat implements Conveyance { public Boat(){; public void moveforward() { System.out.println( "Forward power to propeller"); //moveforward public void slowdown() { System.out.println( "Reverse power to propeller"); //slowdown //Boat public class Boat imp public Boat(){; public void movefo System.out.println "Forwar //moveforward public void slowdo public void stop() { Exempel: state.slowdown(); Klassen Amphicar //stop state = car; //prepareforland //Amphicar public class Amphicar { private Conveyance state; private Conveyance car; private Conveyance boat; public Amphicar() { car = new Car(); boat = new Boat(); state = car; //constructor public void go() { state.moveforward(); //go public void stop() { state.slowdown(); //stop // Turning doesn't depend on the state //so it is implemented here. public void turnright() { System.out.println("Turn wheels right."); //turnright public void turnleft() { System.out.println("Turn wheels left."); //turnleft public void prepareforwater() { state = boat; //prepareforwater public void prepareforland() { state = car; //prepareforland //Amphicar

Exempel: Testprogram public class Main { public static void main(string[] args) { Amphicar a = new Amphicar(); public a.go(); class Main { a.turnright(); public a.stop(); static void main(string[] args) { Amphicar a.prepareforwater(); a = new Amphicar(); a.go(); Testkörning: a.go(); a.turnright(); a.stop(); Forward power to rear wheels a.turnright(); //main Turn wheels right. //Main a.stop(); Apply breaks on each wheel Forward power to propeller a.prepareforwater(); Turn wheels right. a.go(); Reverse power to propeller Testkörning: a.turnright(); a.stop(); //main Forward power to rea Turn wheels right. Designmönstret Model View - Control Designmönstret Model-View-Control (MVC) frikopplar användargränssnittet från den underliggande modellen. MVC delar upp en applikation i tre olika typer av klasser: Model: Den datamodell som används en abstrakt representation av den information som bearbetas i programmet. Utgörs av de klasser som ansvarar för tillståndet i applikationen. View: De klasser som ansvarar för att presentera modellen. Control: De klasser som påverkar modellens tillstånd. Controller View Controller Controller Model View View

Model-View-Control Genom att separera modellen och vyn kan förändringar göras i vyn och flera vyer skapas utan att behöva ändra koden i den underliggande modellen. När tillståndet i modellen förändras skall vyerna uppdateras, vi har alltså designmönstret Observer, mellan modellen och vyn. Model-View-Control Observable +addobserver Observer): void #setchanged(): void +notifyobservers(): void Controller +modify(): void ** ** <<interface>> Observer +update(observable; Object):void Model +somemethod(): void View +update( Observable; Object): void Flera andra varianter på MVC-mönstret är möjliga och finns beskrivna i litteraturen.

MVC och Java När man implementerar MVC-modellen i Java rekommenderas (numera) att använda klassen PropertyChangeSupport och interfacet PropertyChangeListener istället för Observable och Observer. MVC och Java <<interface>> Serializable <<interface>> PropertyChangeListener +propertychange(propertychangeevent) <<interface>> IModel +addpropertychangelistener(...) +removepropertychangelistener(...) * Controller +modify(): void * View {abstract +propertychange(propertychangeevent) Model -pcs: PropertyChangeSupport ConcreteView paintcomponent(graphic) +addpropertychangelistener(...) +removepropertychangelistener(...) //accessors PropertyChangeSupport +addpropertychangelistener(...) +removepropertychangelistener(...) +firepropertychange(...) //more methods I design ovan är inte Model en subklass till PropertyChangeSupport, utan istället har delegering används för att möjliggöra att Model skall kunna ärva från någon annan klass.

PropertyChangeSupport och PropertyChangeListener I klassen PropertyChangeSupport finns bl.a följande metoder: void addpropertychangelistener(propertychangelistener li) lägger till lyssnaren li void removepropertychangelistener(propertychangelistener li) tar bort lyssnaren li void firepropertychange(string propertyname, Object oldvalue, Object newvalue) meddelar alla lyssnare att något har hänt genom att generera en händelse av typen PropertyChangeEvent. oldvalue och newvalue måste vara olika för att verkligen skall genereras. I interfacet PropertyChangeListener finns endast en metod specificerad: void propertychange(propertychangeevent evt) Denna metod anropas när en PropertyChangeEvent inträffar. MVC ett enkelt exempel Vi visar hur MVC-mönstret kan användas genom att skriva ett mycket enkelt program som konverterar temperaturer angivna i Celsius till Kelvin respektive till Farenheit. IModell: import java.beans.*; import java.io.*; public interface IModel extends Serializable { void addpropertychangelistener(propertychangelistener l); void removepropertychangelistener(propertychangelistener l);

Modell: import java.beans.*; public class Model implements IModel { private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); import private java.beans.*; int degreecelsius; public public class Model() Model { implements IModel { degreecelsius = 0; private //constructor final PropertyChangeSupport pcs = new PropertyChang private public void int addpropertychangelistener(propertychangelistener degreecelsius; l) { pcs.addpropertychangelistener(l); public //addpropertychangelistener Model() { public degreecelsius void removepropertychangelistener(propertychangelistener = 0; l) { pcs.removepropertychangelistener(l); //constructor //removepropertychangelistener public int getvalue() { return void degreecelsius; addpropertychangelistener(propertychangelistene Avfyras endast om oldvalue!= newvalue //getvalue pcs.addpropertychangelistener(l); public void setvalue(int newvalue) { //addpropertychangelistener int oldvalue = degreecelsius; public degreecelsius void removepropertychangelistener(propertychangelis = newvalue; pcs.firepropertychange("value", oldvalue, newvalue); //setvalue pcs.removepropertychangelistener(l); //removepropertychangelistener //Model public int getvalue() { return degreecelsius; View: import java.beans.*; import javax.swing.*; public abstract class View extends JPanel implements PropertyChangeListener { protected Model model; public View(Model m) { model = m; model.addpropertychangelistener(this); //setmodel public abstract void propertychange(propertychangeevent e); //View

Konkreta vyer KelvinView: import java.awt.*; import javax.swing.*; import java.beans.*; import public class java.awt.*; KelvinView extends View { private JLabel k = new JLabel(); import public javax.swing.*; KelvinView(Model m) { import super(m); java.beans.*; setpreferredsize(new Dimension(100,100)); public k.setforeground(color.blue); class KelvinView extends View { private setbackground(color.white); JLabel k = new JLabel(); add(new JLabel("Kelvin: ")); public add(k); KelvinView(Model m) { //constructor super(m); public void propertychange(propertychangeevent e) { double setpreferredsize(new tok = model.getvalue()+273.15; Dimension(100,100)); k.settext(string.format("%.2f", tok)); k.setforeground(color.blue); //propertychange //KelvinView setbackground(color.white); add(new JLabel("Kelvin: ")); add(k); //constructor f.settext(string.format("%.2f", tof)); Konkreta //propertychange vyer FarhenheitView: //FahrenheitView import java.awt.*; import javax.swing.*; import java.beans.*; public class FahrenheitView extends View { private JLabel f = new JLabel(); public FahrenheitView(Model m) { super(m); setpreferredsize(new Dimension(100,100)); f.setforeground(color.blue); setbackground(color.white); add(new JLabel("Fahrenheit: ")); add(f); //constructor public void propertychange(propertychangeevent e) { double tof = model.getvalue()*9.0/5.0+32; f.settext(string.format("%.2f", tof)); //propertychange //FahrenheitView

Controller: import javax.swing.*; import java.awt.event.*; public class Controller extends JPanel implements ActionListener { import private javax.swing.*; Model model; private JTextField f = new JTextField(5); import public Controller(Model java.awt.event.*; m) { public model class = m; Controller extends JPanel implements A add(f); private f.addactionlistener(this); Model model; private //constructor JTextField f = new JTextField(5); public void actionperformed(actionevent e) { model.setvalue(integer.parseint(f.gettext())); public Controller(Model m) { //actionperformed model = m; add(f); f.addactionlistener(this); //constructor //Controller public void actionperformed(actionevent e) { //constructor Hopkoppling public av komponenterna: static void main(string[] arg){ MVCDemo demo = new MVCDemo(); import //main java.awt.*; import //MVCDemo javax.swing.*; public class MVCDemo extends JFrame { public MVCDemo() { Model m = new Model(); View kv = new KelvinView(m); View fv = new FahrenheitView(m); Controller c = new Controller(m); setlayout(new FlowLayout()); add(c); add(kv); add(fv); pack(); setvisible(true); setdefaultcloseoperation(exit_on_close); //constructor public static void main(string[] arg){ MVCDemo demo = new MVCDemo(); //main //MVCDemo

Designmönstret Bridge Bridge Abstraction {abstract -impl: Implementor +function() <<interface>> Implementor +implementation() RefinedAbstractionA +function() RefinedAbstractionB +function() ConcreteImplementorA +implementation() ConcreteImplementorB +implementation() function() { impl.implementation(); Att frigöra en abstraktion från sin implementering så att båda kan variera oberoende. Designmönstret Bridge Vehicle Car Bus CarWithBigEngine CarWithSmallEngine BusWithBigEngine BusWithSmallEngine Med användning av designmönstret Bridge Vehicle {abstract +drive(): void <<interface> Engine +go(): void Car Bus SamllEngine BigEngine +drive(): void +drive(): void +go(): void +go(): void

Designmönstret Bridge public abstract class Vehicle { protected Engine engine; protected int weightinkilos; public abstract void drive(); public abstract class Vehicle { public void setengine(engine engine) { protected this.engine Engine = engine; engine; protected int weightinkilos; public void reportonspeed(int horsepower) { public int abstract ratio = weightinkilos void drive(); / horsepower; if (ratio < 3) { public void setengine(engine engine) { this.engine else if ((ratio >= = 3) engine; && (ratio < 8)) { public void reportonspeed(int horsepower) { System.out.println("The vehicle is going at a fast speed."); System.out.println("The vehicle is going an average speed."); else { System.out.println("The vehicle is going at a slow speed."); int ratio = weightinkilos / horsepower; if (ratio < 3) { System.out.println("The vehicle is going at a fast speed else if ((ratio >= 3) && (ratio < 8)) { System.out.println("The vehicle is going an average sp else { Designmönstret Bridge public class Car extends Vehicle { public Car(Engine engine) { this.weightinkilos = 600; this.engine = engine; @Override public void drive() { System.out.println("\nThe car is driving"); //Car int horsepower = engine.go(); reportonspeed(horsepower); System.out.println("\nTh int horsepower = engine. reportonspeed(horsepow //Bus public class Bus extends Vehicle { public Bus(Engine engine) { this.weightinkilos = 3000; this.engine = engine; @Override public void drive() { System.out.println("\nThe bus is driving"); int horsepower = engine.go(); reportonspeed(horsepower); //Bus

Designmönstret Bridge public interface Engine { public int go(); ublic interface Engine { public int go(); public class SmallEngine implements Engine { @Override private public int go() int { horsepower; public System.out.println("The SmallEngine() small { engine is running"); return horsepower; public class BigEngine implements Engine { horsepower = 100; private int horsepower; public BigEngine() { horsepower = 350; @Override public int go() { @Override public go() { System.out.println("The small engine is running"); public class SmallEngine implements Engine { private int horsepower; public SmallEngine() { horsepower = 100; return horsepower; System.out.println("The big engine is running"); return horsepower; //BigEngine public class BigEngine implement private int horsepower; public BigEngine() { horsepower = 350; Designmönstret Bridge The car is driving The big engine is run The vehicle is going public class BridgeDemo { public static void main(string[] args) { Vehicle vehicle = new Bus(new SmallEngine()); vehicle.drive(); vehicle.setengine(new BigEngine()); vehicle.drive(); vehicle = new Car(new SmallEngine()); vehicle.drive(); vehicle.setengine(new BigEngine()); vehicle.drive(); //BridgeDemo The bus is driving The small engine is running The vehicle is going at a slow speed. The bus is driving The big engine is running The vehicle is going at a slow speed. The car is driving The small engine is running The vehicle is going an average speed. The car is driving The big engine is running The vehicle is going at a fast speed.

Designmönstret Iterator Med en iterator kan man förflytta sig igenom en samling av data, utan att behöva känna till detaljer om datans interna representation. Iterator-mönstret är användbart eftersom det tillhandahåller ett definierat sätt att genomlöpa en uppsättning av dataelement, utan att exponera vad som händer inne i klassen. Client <<interface>> Iterator +hasnext(): boolean +next(): Object <<interface>> Collection +iterator(): Iterator ConcreteIterator ConcreteCollection +iterator(): Iterator Designmönstret Iterator :Client :Collection.iterator() <<create>> :Iterator iterator loop() while(iterator.hasnext()).next() next process next

Designmönstret Façade Designmönstret Façade används för att dölja komplexitet för användarna. lättare att använda fasaden än det ursprungliga systemet kan byta implementation av det som fasaden gömmer mindre beroenden Libary Client -facade: Facade SubsystemA SubsystemB SubsystemC Facade -a: SubsystemA -b: SybsystemB -c: SubsystemC +operation1() +operation2() Designmönstret Façade class SubsystemA { String A1() { return "Subsystem A, Method A1\n"; String A2() { return "Subsystem A, Method A2\n"; class SubsystemB { String B1() { return "Subsystem B, Method B1\n"; class SubsystemC { String C1() { return "Subsystem C, Method C1\n"; public class Facade { private SubsystemA a = new SubsystemA(); private SubsystemB b = new SubsystemB(); private SubsystemC c = new SubsystemC(); public void operation1() { System.out.println("Operation 1\n" + + a.a1() + a.a2() + b.b1()); public void operation2() { System.out.println("Operation 2\n" + b.b1() + c.c1()); public static void Facade facade facade.operatio facade.operatio public class Client { public static void main (String[] arg) { Facade facade = new Facade(); facade.operation1(); facade.operation2();

Designmönstret Command Designmönstret Command kapslar in kommandon som objekt och låter klienter få tillgång till olika uppsättningar med kommandon. <create> Client Invoker <<interface>> Command +execute(): void Receiver action() ConcreteCommand -receiver: Receiver +execute(): void receiver.action() Designmönstret Command //Command public interface Order { public abstract void execute ( ); //Order // Receiver class. public class StockTrade { public void buy() { System.out.println("You want to buy stocks"); //buy public void sell() { System.out.println("You want to sell stocks "); //sell //StockTrade // Invoker. public class Agent { public Agent() { public void placeorder(order order) { order.execute(); //placeorder //Agent

Designmönstret Command //ConcreteCommand class. public class BuyStockOrder implements Order { private StockTrade stock; public BuyStockOrder(StockTrade st) { stock = st; //constructor public void execute( ) { stock.buy( ); //execute //BuyStockOrder // Client public class Client { public static void main(string[] args) { StockTrade stock = new StockTrade(); BuyStockOrder bsc = new BuyStockOrder (stock); SellStockOrder ssc = new SellStockOrder (stock); Agent agent = new Agent(); agent.placeorder(bsc); // Buy Shares agent.placeorder(ssc); // Sell Shares //main //Client //ConcreteCommand class. public class SellStockOrder implements Order { private StockTrade stock; public SellStockOrder(StockTrade st) { stock = st; //constructor public void execute( ) { stock.sell( ); //execute //SellStockOrder