Download præsentationen
Præsentation er lastning. Vent venligst
Offentliggjort afArne Kristiansen Redigeret for ca. et år siden
1
Designmønstre Composite, Template Method, Strategy og State
Michael E. Caspersen Datalogisk Institut Aarhus Universitet
2
Dagens emner Composite Template Method Strategy State
Definition á la GoF Eksempler Template Method Strategy State Programmeringsteknologi, F11 Designmønstre
3
Composite
4
Opgave 3.A: Model for PowerPoint
Der skal laves et system á la PowerPoint der kan lave dias som indeholder både tekst og grafik. Systemet skal være effektivt, brugervenligt og med mulighed for senere udvidelse af funktionaliteten. Systemet skal være et WYSIWYG-system hvor brugeren løbende skal kunne se hvordan den færdige præsentation kommer til at se ud. Tilsvarende skal det være muligt at ændre layout og indhold af præsentationens dias på en simpel måde og gennem direkte manipulation af elementerne i hvert dias. For eksempel skal man kunne lave en figur på et dias ved at lægge et grafisk billede og en billedtekst ind, og få tegnet en kasse rundt om. Det skal være muligt at skifte størrelse på figuren, og kassens størrelse skal da følge figurens størrelse. Det skal være muligt at flytte figuren både sammen med og uafhængigt af teksten (dog ikke samtidig :-). Det skal være muligt at gruppere elementer i et dias således at disse kan manipuleres under et (for eksempel ved flytning, kopiering, animering, etc.). Lav en klassemodel for centrale dele af den her skitserede applikation. Programmeringsteknologi, F11 Designmønstre
5
En løsning (begrebsmodel)
void move(int dx, int dy) Item copy() void scaleHorizontal(int sf) void scaleVertical(int sf) void scaleLockedRatio(int sf) void rotate(int angle) order(int level) ... * Presentation Dias * * Item Text Picture Graphics Group Programmeringsteknologi, F11 Designmønstre
6
Udtryk (projektopgave nr. 2)
1 2 Exp UnaryExp Num Identifier BinaryExp Programmeringsteknologi, F11 Designmønstre
7
Composite á la (1) Intent Motivation
Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly. Motivation Programmeringsteknologi, F11 Designmønstre
8
Composite á la (2) Structure Object structure
Programmeringsteknologi, F11 Designmønstre
9
Composite á la (3) Component (Graphic)
declares the interface for objects in the composition implements default behavior for the interface common to all classes, as appropriate declares an interface for accessing and managing its child components (optional) defines an interface for accessing a component's parent in the recursive structure, and implements it if that's appropriate Leaf (Rectangle, Line, Text, etc.) represents leaf objects in the composition; a leaf has no children defines behavior for primitive objects in the composition Composite (Picture) defines behavior for components having children stores child components implements child-related operations in the Component interface Client manipulates objects in the composition through the Component interface Programmeringsteknologi, F11 Designmønstre
10
Composite á la (4) Consequences of the Composite Pattern
Defines class hierarchies consisting of primitive objects and composite objects. Primitive objects can be composed into more complex objects, which in turn can be composed, and so on recursively. Wherever client code expects a primitive object, it can also take a composite object. Makes the client simple. Clients can treat composite structures and individual objects uniformly. Clients normally don't know (and shouldn't care) whether they're dealing with a leaf or a composite component. This simplifies client code, because it avoids having to write tag-and-case-statement-style functions over the classes that define the composition. Makes it easier to add new kinds of components. Newly defined Composite or Leaf subclasses work automatically with existing structures and client code. Clients don't have to be changed for new Component classes. Can make your design overly general. The disadvantage of making it easy to add new components is that it makes it harder to restrict the components of a composite. Sometimes you want a composite to have only certain components. With Composite, you can't rely on the type system to enforce those constraints for you. You'll have to use run-time checks instead. Programmeringsteknologi, F11 Designmønstre
11
GUI-komponenter (Java)
En GUI består af en række grafiske komponenter knapper, lister, tekstfelter Disse fremstår i et visuelt layout i en grafisk container en applet, en dialogboks, et vindue, eller et selvstændigt vinduesbaseret program (frame) Betegnelsen Container er velvalgt indeholder polymorfe objekter nøjagtig som Collections Programmeringsteknologi, F11 Designmønstre
12
java.awt.Component Component, ej Container Container
Programmeringsteknologi, F11 Designmønstre
13
Kompositionshierarkier
Enhver GUI i Java er et kompositionshierarki Et antal komponenter i en container: anApplet aCanvas aPanel aButton aButton aChoice Container Component, ej Container Programmeringsteknologi, F11 Designmønstre
14
Template Method
15
Generalisering af kaffe- og tebrygning
Kaffe-opskrift Kog vand Bryg kaffe med kogende vand Hæld kaffe i kop Kom mælk og sukker i Te-opskrift Kog vand steep Lad te trække i kogende vand Hæld te i kop Kom citron i Abstraktion: Generalisering Opskrift for brygning af varme drikke Kog vand Udtræk smagsstof i kogende vand Hæld drik i kop Kom tilsætningsstoffer i Programmeringsteknologi, F11 Designmønstre
16
Java-brygning af varme drikke
abstract class CaffeineBeverage { final void prepareRecipe() { boilWater(); brew(); pourInCup(); addCondiments(); } abstract void brew(); abstract void addCondiments(); class Tea extends CaffeineBeverage { void brew() { ... } void addCondiments() { ... } } class Coffee extends CaffeineBeverage { abstract void brew() { ... } abstract void addCondiments() { ... } } Programmeringsteknologi, F11 Designmønstre
17
Template Method á la (1) Intent Motivation
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure. Motivation Invariant Variant Programmeringsteknologi, F11 Designmønstre
18
Template Method á la (2) Structure Participants
AbstractClass (Application) defines abstract primitive operations that concrete subclasses define to implement steps of an algorithm implements a template method defining the skeleton of an algorithm. The template method calls primitive operations as well as operations defined in AbstractClass or those of other objects ConcreteClass (MyApplication) implements the primitive operations to carry out subclass-specific steps of the algorithm . Programmeringsteknologi, F11 Designmønstre
19
Template Method á la (3) Consequences
Template methods are a fundamental technique for code reuse. They are particularly important in class libraries, because they are the means for factoring out common behavior in library classes. Template methods lead to an inverted control structure that's sometimes referred to as "the Hollywood principle”, that is, "Don't call us, we'll call you". This refers to how a parent class calls the operations of a subclass and not the other way around. Programmeringsteknologi, F11 Designmønstre
20
Eksempel: Grafik abstract class TegneObjekt { private int x, y;
public final void move(int dx, int dy) { hide(); x += dx; y += dy; show(); } public abstract void show(); public abstract void hide(); Programmeringsteknologi, F11 Designmønstre
21
Eksempel: Undtagelseshåndtering
class MyStack extends Stack { private void handleUnderflow() { ”fejlhåndtering som passer til min applikation” } class Stack { ... public final void pop(Object e) { if (isEmpty()) handleUnderflow(); else ”normal situation” } private void handleUnderflow() {} Hook method: En metode erklæret i en abstrakt klasse med default implementation (evt. tom). Open-Closed Principle: Moduler skal være åbne for udvidelser, men lukkede for modifikation. — If it ain’t broke, don’t fix it! Programmeringsteknologi, F11 Designmønstre
22
Strategy
23
Strategy á la (1) Intent Structure
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it. Structure Programmeringsteknologi, F11 Designmønstre
24
Strategy á la (2) Participants Strategy
Declares an interface common to all supported algorithms. Context uses this interface to call the algorithm defined by a ConcreteStrategy Implements a template method defining the skeleton of an algorithm. The template method calls primitive operations as well as operations defined in AbstractClass or those of other objects. ConcreteStrategy implements the algorithm using the Strategy interface. Context is configured with a ConcreteStrategy object maintains a reference to a Strategy object may define an interface that lets Strategy access its data Programmeringsteknologi, F11 Designmønstre
25
Eksempel: GUI i Java Mange tidligere tilgange til layout har været direkte koordinatbaserede: Denne tilgang er “uheldig”: det er meget svært at kode en GUI tekstuelt x y changeButton.setSize(20,50); changeButton.setPosition(80, 60); Programmeringsteknologi, F11 Designmønstre
26
Alternativ til koordinatbasering
Første bud på en løsning: GUI-Builders interaktive værktøjer hvor man kan editere sin GUI grafisk genererer derefter koordinatbaseret kildetekst Men det er ikke godt nok Java skal være platformuafhængigt men størrelsen af knapper, skrifttyper m.m. varierer fra platform til platform... I stedet for absolut placering specificeres den relative placering af komponenterne i en GUI LayoutManagers har ansvaret for placering af komponenter i containere Programmeringsteknologi, F11 Designmønstre
27
LayoutManager Layoutet af componenterne i en container bestemmes af containerens LayoutManager Ikke den absolutte, men den relative placering af komponenterne specificeres Positionen og størrelsen af komponenterne vil automatisk blive justeret når vinduets størrelse ændres Programmeringsteknologi, F11 Designmønstre
28
FlowLayout width = 400 height = 50 width = 100 height = 200
Programmeringsteknologi, F11 Designmønstre
29
FlowLayout (2) public class Flow extends Applet { public Flow () {
// FlowLayout is default, but ... setLayout(new FlowLayout()); add(new Button("Java")); add(new Button("C++")); add(new Button("Perl")); add(new Button("Ada")); add(new Button("Smalltalk")); add(new Button("Eiffel")); } Programmeringsteknologi, F11 Designmønstre
30
BorderLayout Programmeringsteknologi, F11 Designmønstre
31
BorderLayout (2) import java.awt.*; import java.applet.Applet;
public class Border extends Applet { public Border () { setLayout(new BorderLayout()); add("South", new Button("South")); add("North", new Button("North")); add("East", new Button("East")); add("West", new Button("West")); add("Center", new Button("Center")); } Programmeringsteknologi, F11 Designmønstre
32
GridLayout row = 1 col = 0 row = 3 row = 0 col = 2 col = 1
Programmeringsteknologi, F11 Designmønstre
33
GridLayout (2) public class Grid extends Applet {
public void init () { int row = 0, col = 0; // row = ...; // col = ...; setLayout(new GridLayout(row, col)); add(new Button("Java")); add(new Button("C++")); add(new Button("Perl")); add(new Button("Ada")); add(new Button("Smalltalk")); add(new Button("Eiffel")); } Programmeringsteknologi, F11 Designmønstre
34
Nestede paneler Programmeringsteknologi, F11 Designmønstre
35
Nestede paneler (2) public class NestedPanels extends Applet {
public NestedPanels () { Panel center = new Panel(); ... Panel south = new Panel(); setLayout(new BorderLayout()); add("North", new Button("North")); add("East", new Button("East")); add("West", new Button("West")); add("South", south); add("Center", center); } protected Label messageBar; protected Choice choice; Programmeringsteknologi, F11 Designmønstre
36
Nestede paneler (3) Panel center = new Panel();
center.setLayout(new BorderLayout()); center.add("South", new Button(”Syd")); center.add("North", new Button(”Nord")); center.add("East", new Button(”Øst")); center.add("West", new Button(”Vest")); center.add("Center", new Button(”Center")); Panel south = new Panel(); south.setLayout(new FlowLayout()); south.add(new Button("Help")); choice = new Choice(); choice.addItem("one"); choice.addItem("two"); choice.addItem("three"); choice.addItem("four"); choice.addItem("five"); south.add(choice); messageBar = new Label("This is a message bar."); south.add(messageBar); Programmeringsteknologi, F11 Designmønstre
37
Andre LayoutManagere CardLayout GridBagLayout Din helt egen manager
hver komponent fylder det hele fungerer som kort ovenpå hinanden GridBagLayout yderst fleksibel, men kompliceret Din helt egen manager ved at udvide LayoutManager, kan man definere sin egen LayoutManager ColumnLayout, udlægger komponenter i deres standardstørrelse som FlowLayout, men fra oven og nedefter (se f.eks. “Java Examples in a Nutshell”) Programmeringsteknologi, F11 Designmønstre
38
LayoutManager, hierarkiet
Strategy 1 setLayout (LayoutManager lm) Programmeringsteknologi, F11 Designmønstre
39
Søgeskabelon Søgedomæne: S Kandidatmængde: K kandidatelement : e
kandidatelement : e Målelement : m I et søgedomæne, S, søger vi efter et målelement, m. På et givet tidspunkt under søgningen har vi afsøgt en del af søgedomænet; den resterende del kalder vi kandidatmængden, K. Et skridt i søgningen består i at vælge et (tilfældigt) kandidatelement, e, fra kandidatmængden og sammenligne dette med målelementet m. Enten har vi fundet det vi søger, eller også afskærer vi en del af kandidatmængden. Søgningen slutter når vi har fundet det vi søger eller når kandidatmængden er tom. Programmeringsteknologi, F11 Designmønstre
40
Søgeskabelon, algoritmisk
initialiser K ; found = false ; while ( !found && K Ø ) { udvælg e fra K ; if ( e == m ) found = true ; else split K ; } Programmeringsteknologi, F11 Designmønstre
41
Konkretisering af skabelonen
initialiser K : K Ø : udvælg e fra K : split K : s[0..s.size()) i = 0; i != s.size() e = s.elementAt(i); i++; s: e i Programmeringsteknologi, F11 Designmønstre
42
Lineær søgning public static boolean search(int m, Sequence s) {
// post: returnerer om m findes i s boolean found; // resultat-variabel i = 0; found = false; while ( !found && i != s.size() ) { int e = s.elementAt(i); if ( e == m ) found = true; else i++; } return found; Programmeringsteknologi, F11 Designmønstre
43
Binær søgning S : initialiser K : K Ø : udvælg e fra K : split K :
mi h S : initialiser K : K Ø : udvælg e fra K : split K : s[0..s.size()) l = 0 ; h = s.size(); l < h mi = (l+h)/2; e = s.elementAt(mi) if ( e < m ) l = mi+1; else // e > m h = mi; Programmeringsteknologi, F11 Designmønstre
44
Bineær søgning (Java) public static boolean search(int m, Sequence s) { // pre: s er sorteret ( ) // post: returnerer om m findes i s boolean found; // resultat-variabel l = 0; h = s.size(); found = false; while ( !found && l<h ) { int mi = (l+h)/2; int e = s.elementAt(mi); if ( e == m ) found = true; else if ( e < m ) l = mi+1; else // e > m h = mi; } return found; Programmeringsteknologi, F11 Designmønstre
45
Søgeskabelon realiseret med Strategy
<<interface>> Searchable Searcher void init() boolean isEmpty() select() split(Object e) search() SomeList SomeTree void init() boolean isEmpty() select() split(Object e) void init() boolean isEmpty() select() split(Object e) Programmeringsteknologi, F11 Designmønstre
46
Genericity vha. interfaces
interface Searchable<T> { public void init(); public boolean isEmpty(); public T select(); public void split(T e); } public static <T> boolean search(Searchable s, T m) { // assuming element type to implement equals s.init(); boolean found = false; while ( !found && !s.isEmpty() ) { T e = s.select(); if (e.equals(m) ) found = true; else s.split(e); } return found; Programmeringsteknologi, F11 Designmønstre
47
Template Method versus Strategy
Begge mønstre er eksempler på udfaktorisering a*b + a*c = a*(b+c) Begge mønstre separerer en generisk algoritme fra specifikke kontekster Template Method Den generiske algoritme faktoriseres til en abstrakt superklasse Specifik kontekst konkretiseres i subklasser Strategy Den generiske algoritme faktoriseres til en konkret klasse Specifik kontekst abstraheres til et interface Generisk algoritme delegerer til specifik kontekst via interface Programmeringsteknologi, F11 Designmønstre
48
State
49
State og Strategy Det er de færreste der ved det, men …
Strategy og State er tvillinger der blev separeret ved fødslen. Strategy har skabt sig en succesfuld forretning omkring udskiftbare algoritmer. State gik en anden vej og hjælper objekter med at kontrollere deres opførsel ved at ændre deres interne tilstand. Cryptomathic, F05 Designmønstre
50
Mighty Gumball Inc. inserts quarter No Quarter Has Quarter
Out of Gumballs Gumball Sold No Quarter Has Quarter inserts quarter ejects quarter turns crank dispense gumball (#gumballs > 0) (#gumballs = 0) Cryptomathic, F05 Designmønstre
51
FSM State (tilstand) Event (hændelse) No Quarter Has Quarter
Gumball Sold Out of gumballs Event (hændelse) inserts quarter ejects quarter turns crank dispense gumball Out of Gumballs Gumball Sold No Quarter Has Quarter inserts quarter ejects quarter turns crank dispense gumball (#gumballs > 0) (#gumballs = 0) Cryptomathic, F05 Designmønstre
52
Modellering af FSM i software
Nestede switch-sætninger (softwaretabel) switch state ... switch event switch event ... switch state Datastruktur 2-dimensionalt array Out of Gumballs Gumball Sold No Quarter Has Quarter inserts quarter ejects quarter turns crank dispense gumball (#gumballs > 0) (#gumballs = 0) Events States Handling Ny tilstand Cryptomathic, F05 Designmønstre
53
Tilstande og events som tal
Out of Gumballs Gumball Sold No Quarter Has Quarter inserts quarter ejects quarter turns crank dispense gumball (#gumballs > 0) (#gumballs = 0) final static int INSERT_QUARTER = 0; final static int EJECT_QUARTER = 1; final static int TURN_CRANK = 2; final static int DISPENSE_GUMBALL = 3; final static int NO_QUARTER = 0; final static int HAS_QUARTER = 1; final static int SOLD = 2; final static int SOLD_OUT = 3; int event = INSERT_QUARTER; int state = NO_QUARTER; Cryptomathic, F05 Designmønstre
54
Eventhandler public void eventHandler(int event) { switch event {
Out of Gumballs Gumball Sold No Quarter Has Quarter inserts quarter ejects quarter turns crank dispense gumball (#gumballs > 0) (#gumballs = 0) public void eventHandler(int event) { switch event { INSERT_QUARTER: insertQuarter(); break; EJECT_QUARTER: ejectQuarter(); break; TURN_CRANK: turnCrank(); break; DISPENSE_GUMBALL: dispenseGumball(); break; } Cryptomathic, F05 Designmønstre
55
insertQuarter() // eventhandler for INSERT_QUARTER
Out of Gumballs Gumball Sold No Quarter Has Quarter inserts quarter ejects quarter turns crank dispense gumball (#gumballs > 0) (#gumballs = 0) // eventhandler for INSERT_QUARTER public void insertQuarter() { switch state NO_QUARTER: state = HAS_QUARTER; println(”You inserted a quarter”); break; HAS_QUARTER: error(”You can’t insert another quarter, turn the crank”); SOLD: error(”Please wait, we are already giving you a gumball”); SOLD_OUT: error(”You can’t buy a gumball, the machine is sold out”); } public void ejectQuarter() { ... } public void turnCrank() { ... ; dispenseGumball(); } public void dispenseGumball() { ... } Cryptomathic, F05 Designmønstre
56
Eller omvendt... Statehandler
Out of Gumballs Gumball Sold No Quarter Has Quarter inserts quarter ejects quarter turns crank dispense gumball (#gumballs > 0) (#gumballs = 0) public void stateHandler(int event) { switch state { NO_QUARTER: noQuarter(); break; HAS_QUARTER: hasQuarter(); break; SOLD: sold(); break; SOLD_OUT: soldOut(); break; } Cryptomathic, F05 Designmønstre
57
noQuarter() // statehandler for NO_QUARTER public void noQuarter() {
Out of Gumballs Gumball Sold No Quarter Has Quarter inserts quarter ejects quarter turns crank dispense gumball (#gumballs > 0) (#gumballs = 0) // statehandler for NO_QUARTER public void noQuarter() { switch event INSERT_QUARTER: state = HAS_QUARTER; println(”You inserted a quarter”); break; EJECT_QUARTER: error(”Sorry, there is no quarter to eject”); TURN_CRANK: error(”Please insert a quarter”); DISPENSE_GUMBALL: debug(”illegal event in state NO_QUARTER”); } public void hasQuarter() { ... } public void sold() { ... } public void soldOut() { ... } Cryptomathic, F05 Designmønstre
58
Nye krav (det måtte jo komme...)
Vi gør tyggegummikøb til et spil og forøger vores salg betragteligt!!! En sticker på hver maskine skal lokke kunderne til vores maskiner. Og med Java inden i bliver det en leg... Be a Winner! One in Ten get a FREE GUMBALL Cryptomathic, F05 Designmønstre
59
Øvelse Be a Winner! One in Ten get a FREE GUMBALL Lav en tilstandsmaskine til en tyggegummimaskine der kan klare ”One in a Ten” kravet. 10% af gangene skal der dispenseres to kugler i stedet for en. Cryptomathic, F05 Designmønstre
60
Løsning inserts quarter No Quarter Has Quarter ejects quarter
dispense 2 gumballs (#gumballs > 0) turns crank, winner Winner Out of Gumballs dispense gumball (#gumballs > 0) turns crank, no winner dispense gumball (#gumballs = 0) Gumball Sold dispense 2 gumballs (#gumballs = 0) Cryptomathic, F05 Designmønstre
61
Og så ændringerne i koden... (suk!)
final static int NO_QUARTER = 0; final static int HAS_QUARTER = 1; final static int SOLD = 2; final static int SOLD_OUT = 3; final static int WINNER = 4; // eventhandler for INSERT_QUARTER public void insertQuarter() { switch state NO_QUARTER: state = HAS_QUARTER; println(”You inserted a quarter”); break; HAS_QUARTER: error(”You can’t insert another quarter, turn the crank”); SOLD: error(”Please wait, we are already giving you a gumball”); SOLD_OUT: error(”You can’t buy a gumball, the machine is sold out”); WINNER: } public void ejectQuarter() { ... WINNER: ... } public void turnCrank() { ... WINNER: ... ; dispenseGumball(); } public void dispenseGumball() { ... WINNER: ... } Cryptomathic, F05 Designmønstre
62
Karakteristik af softwaredesignet, sæt kryds
X Koden overholder ikke open/closed principper Koden ville gøre en FORTRAN-programmør stolt Designet er ikke specielt objekt-orienteret Tilstandsovergange er ikke eksplicitte; de er begravet dybt inde i et virvar af switch-sætninger Vi har ikke indkapslet det der varierer Tilføjelser vil højst sandsynligt introducere fejl i gammel kode X X X X X Cryptomathic, F05 Designmønstre
63
Nyt design Først definerer vi et State interface
indeholder en metode for hver hændelse Dernæst implementerer vi en State klasse for hver konkret tilstand i maskinen disse klasser har ansvar for maskinens opførsel når den er i den pågældende tilstand Til sidst kan vi få ryddet op i alle switch-sætningerne i stedet delegeres til state-objekterne der gør arbejdet for os (dynamisk binding erstatter conditionals) Cryptomathic, F05 Designmønstre
64
<<interface>>
Klassedesign <<interface>> State insertQuarter() ejectQuarter() turnCrank() dispenseGumball() SoldState insertQuarter() ejectQuarter() turnCrank() dispenseGumball() SoldOutState NoQuarterState HasQuarterState WinnerState insertQuarter() ejectQuarter() turnCrank() dispenseGumball() Cryptomathic, F05 Designmønstre
65
Specifikation af opførsel...
Out of Gumballs Gumball Sold No Quarter Has Quarter inserts quarter ejects quarter turns crank dispense gumball (#gumballs > 0) (#gumballs = 0) NoQuarterState insertQuarter() ejectQuarter() turnCrank() dispenseGumball() Skift til HasQuarterState Giv besked om at der ikke er indbetalt en krone SoldState insertQuarter() ejectQuarter() turnCrank() dispenseGumball() Giv besked om at vente Aflever en kugle. Check om der er flere kugler; hvis der er skiftes til NoQuarterState og ellers skiftes til SoldOutState Cryptomathic, F05 Designmønstre
66
<<interface>>
Klassestruktur Gumball Machine <<interface>> State insertQuarter() ejectQuarter() turnCrank() dispenseGumball() ... 1 * insertQuarter() ejectQuarter() turnCrank() dispenseGumball() 1 SoldState insertQuarter() ejectQuarter() turnCrank() dispenseGumball() SoldOutState NoQuarterState HasQuarterState WinnerState insertQuarter() ejectQuarter() turnCrank() dispenseGumball() Cryptomathic, F05 Designmønstre
67
Eventhandler . Delegering til State-objekt
public class GumballMachine { State soldOutState; State noQuarterState; State hasQuarterState; State soldState; public GumballMachine(int numberGumballs) { soldOutState = new SoldOutState(this); ... this.count = numberGumballs; if (numberGumballs > 0) { state = noQuarterState; } else { state = soldOutState; } } public void insertQuarter() { state.insertQuarter(); } public void ejectQuarter() { state.ejectQuarter(); } public void turnCrank() { state.turnCrank(); state.dispense(); } . Delegering til State-objekt Cryptomathic, F05 Designmønstre
68
Implementation af NoQuarterState
public class NoQuarterState implements State { GumballMachine gumballMachine; public NoQuarterState(GumballMachine gumballMachine) { this.gumballMachine = gumballMachine; } public void insertQuarter() { System.out.println("You inserted a quarter"); gumballMachine.setState(gumballMachine.getHasQuarterState()); public void ejectQuarter() { System.out.println("You haven't inserted a quarter"); public void turnCrank() { System.out.println("You turned, but there's no quarter"); public void dispense() { System.out.println("You need to pay first"); public String toString() { return "waiting for quarter"; Out of Gumballs Gumball Sold No Quarter Has Quarter inserts quarter ejects quarter turns crank dispense gumball (#gumballs > 0) (#gumballs = 0) Cryptomathic, F05 Designmønstre
69
Implementation af SoldState
public class SoldState implements State { GumballMachine gumballMachine; public SoldState(GumballMachine gumballMachine) { this.gumballMachine = gumballMachine; } public void insertQuarter() { System.out.println("Please wait, we're already giving you a gumball"); public void ejectQuarter() { System.out.println("Sorry, you already turned the crank"); public void turnCrank() { System.out.println("Turning twice doesn't get you another gumball!"); public void dispense() { gumballMachine.releaseBall(); if (gumballMachine.getCount() > 0) { gumballMachine.setState(gumballMachine.getNoQuarterState()); } else { System.out.println("Oops, out of gumballs!"); gumballMachine.setState(gumballMachine.getSoldOutState()); Out of Gumballs Gumball Sold No Quarter Has Quarter inserts quarter ejects quarter turns crank dispense gumball (#gumballs > 0) (#gumballs = 0) Cryptomathic, F05 Designmønstre
70
Øvelse Implementer klasserne HasQuarterState og WinnerState.
Out of Gumballs Gumball Sold No Quarter Has Quarter inserts quarter ejects quarter turns crank, no winner dispense gumball (#gumballs > 0) (#gumballs = 0) Winner winner dispense 2 gumballs Cryptomathic, F05 Designmønstre
71
Løsning (Winner) public class GumballMachine { State soldOutState;
State noQuarterState; State hasQuarterState; State soldState; State winnerState public GumballMachine(int numberGumballs) { soldOutState = new SoldOutState(this); ... winnerState = new WinnerState(this); this.count = numberGumballs; if (numberGumballs > 0) { state = noQuarterState; } else { state = soldOutState; } } public void insertQuarter() { state.insertQuarter(); } public void ejectQuarter() { state.ejectQuarter(); } public void turnCrank() { state.turnCrank(); state.dispense(); } Cryptomathic, F05 Designmønstre
72
WinnerState Samme som SoldState .
public class WinnerState implements State { GumballMachine gumballMachine; public WinnerState(GumballMachine gumballMachine) { this.gumballMachine = gumballMachine; } public void insertQuarter() { ... } public void ejectQuarter() { ... } public void turnCrank() { ... } // pre: gumballMachine.getCount() > 1 public void dispense() { System.out.println("YOU'RE A WINNER! You get two gumballs"); gumballMachine.releaseBall(); if (gumballMachine.getCount() > 0) { gumballMachine.setState(gumballMachine.getNoQuarterState()); } else { System.out.println("Oops, out of gumballs!"); gumballMachine.setState(gumballMachine.getSoldOutState()); Samme som SoldState . Cryptomathic, F05 Designmønstre
73
Implementation af HasQuarterState
public class HasQuarterState implements State { Random randomWinner = new Random(System.currentTimeMillis()); GumballMachine gumballMachine; public void turnCrank() { System.out.println("You turned..."); int winner = randomWinner.nextInt(10); if ((winner == 0) && (gumballMachine.getCount() > 1)) { gumballMachine.setState(gumballMachine.getWinnerState()); } else { gumballMachine.setState(gumballMachine.getSoldState()); } ... Se tilstandsmaskinen næste side... Cryptomathic, F05 Designmønstre
74
Tilstandsmaskinen, igen...
Out of Gumballs Gumball Sold No Quarter Has Quarter inserts quarter ejects quarter turns crank, no winner dispense gumball (#gumballs > 0) (#gumballs = 0) Winner winner dispense 2 gumballs Cryptomathic, F05 Designmønstre
75
Diskussion WinnerState har meget til fælles med SoldState; hvad kan man gøre ved det? Out of Gumballs Gumball Sold No Quarter Has Quarter inserts quarter ejects quarter turns crank, no winner dispense gumball (#gumballs > 0) (#gumballs = 0) Winner winner dispense 2 gumballs Cryptomathic, F05 Designmønstre
76
Testing... It rocks!!! Be a Winner! One in Ten get a FREE GUMBALL
public class GumballMachineTestDrive { public static void main(String[] args) { GumballMachine gumballMachine = new GumballMachine(5); System.out.println(gumballMachine); gumballMachine.insertQuarter(); gumballMachine.turnCrank(); } It rocks!!! Be a Winner! One in Ten get a FREE GUMBALL Cryptomathic, F05 Designmønstre
77
State á la (1) Intent Motivation
Allow an object to alter its behavior when its internal state changes. The object will appear to change its class. Motivation Invariant Variant Cryptomathic, F05 Designmønstre
78
State á la (2) Structure Participants
Context (GumballMachine, TCPConnection) defines the interface of interest to clients. maintains an instance of a ConcreteState subclass that defines the current state. State ((Gumball) State, TCPState) defines an interface for encapsulating the behavior associated with a particular state of the Context. ConcreteState subclasses (NoQuarter, HasQuarter, ..., TCPEstablished, TCPListen, TCPClosed) each subclass implements a behavior associated with a state of the Context. Cryptomathic, F05 Designmønstre
79
State á la (3) Consequences
It localizes state-specific behavior and partitions behavior for different states. The State pattern puts all behavior associated with a particular state into one object. Because all state-specific code lives in a State subclass, new states and transitions can be added easily by defining new subclasses. It makes state transitions explicit. When an object defines its current state solely in terms of internal data values, its state transitions have no explicit representation; they only show up as assignments to some variables. Introducing separate objects for different states makes the transitions more explicit. Also, State objects can protect the Context from inconsistent internal states, because state transitions are atomic from the Context's perspective—they happen by rebinding one variable. Cryptomathic, F05 Designmønstre
80
State versus Strategy Hvad er forskellen? Intention!
State: Allow an object to alter its behavior when its internal state changes. The object will appear to change its class Strategy: Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it. Cryptomathic, F05 Designmønstre
81
Composite, Template Method, Strategy og State
Programmeringsteknologi, F11 Designmønstre
Lignende præsentationer
© 2024 SlidePlayer.dk Inc.
All rights reserved.