© 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a...

20
© 2006 Pearson Education Design Patterns 1 of 20 A Final Example: A Traffic Light • Let’s model a traffic light! here’s the spec: Have a column of two circles representing lights. When the program starts, the top light should be red (on) and the bottom one black (off). Beneath the lights should be a button. When this button is pressed, the lights should change their state so that the top one is black (off) and the bottom one is green (on). The next time the button is pressed, the red light becomes active. Each time the button is pressed, the lights will toggle between red and green. • Note a subtle difference between this example and the ShapeColorChanger: for the ShapeColorChanger, the state of the color changer was remembered by the column of radio buttons this traffic light example will have no such radio button column a new design pattern (the “State” pattern) will have to be used to keep track of the state

Transcript of © 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a...

Page 1: © 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a traffic light! – here’s the spec: Have a column of two circles.

© 2006 Pearson EducationDesign Patterns

1 of 20

A Final Example: A Traffic Light

• Let’s model a traffic light!– here’s the spec:

Have a column of two circles representing lights. When the program starts, the top light should be red (on) and the bottom one black (off). Beneath the lights should be a button. When this button is pressed, the lights should change their state so that the top one is black (off) and the bottom one is green (on). The next time the button is pressed, the red light becomes active. Each time the button is pressed, the lights will toggle between red and green.

• Note a subtle difference between this example and the ShapeColorChanger:– for the ShapeColorChanger, the state of the color

changer was remembered by the column of radio buttons

– this traffic light example will have no such radio button column

– a new design pattern (the “State” pattern) will have to be used to keep track of the state

Page 2: © 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a traffic light! – here’s the spec: Have a column of two circles.

© 2006 Pearson EducationDesign Patterns

2 of 20

Analyzing the Specification

• We’ll start by underlining nouns:

Have a column of two circles representing lights. When the program starts, the top light should be red (on) and the bottom one black (off). Beneath the lights should be a button. When this button is pressed, the lights should change their state so that the top one is black (off) and the bottom one is green (on). The next time the button is pressed, the red light becomes active. Each time the button is pressed, the lights will toggle between red and green.

• Some we don’t have to deal with because they have been provided– JPanels, gfx.ColorEllipse, and JButton

• Let’s focus on the one new noun:– state

Page 3: © 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a traffic light! – here’s the spec: Have a column of two circles.

© 2006 Pearson EducationDesign Patterns

3 of 20

Class Diagram

• Most of design is simple– Frame contains TrafficLight– TrafficLight contains Lights and button that

changes Lights (and probably a QuitButton too)– also contains something that models how it responds

to button being pressed

• What can we do to model the state of the light?

= “contains multiple instances of”Frame

TrafficLight

??? Light LightChangeButton

Page 4: © 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a traffic light! – here’s the spec: Have a column of two circles.

© 2006 Pearson EducationDesign Patterns

4 of 20

States and State Diagrams

• What do we need?– something that encapsulates TrafficLight’s

response to user clicking button– make subclasses that model possible responses– but how do we know when to add and remove each

response?

• State: n. 1. a mode or condition of being– State Diagrams represent an exhaustive (i.e.,

complete) enumeration of an object’s possible states and how to move between them

– graphical notation that helps you understand dynamic behavior of object

• State Diagrams are composed of states and transitions among them– recall that object’s state is value of its properties at a

given moment in time– object’s methods change those values, thus cause

object to make a transition, i.e., “move” between states

– think of method as a stimulus, transition to next state as response

• Let’s see an example!

Page 5: © 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a traffic light! – here’s the spec: Have a column of two circles.

© 2006 Pearson EducationDesign Patterns

5 of 20

Reading a State Diagram

• State Diagrams are programming language independent– graphical notation like class and instance diagrams

• but have very different semantic meaning– states are represented by a circle

• start states are denoted by a “>” next to a circle• final states are denoted by a double circle

– transitions are represented by an arc linking two circles• transitions are marked by arrows because they are

directed• transitions describe a sequence of method calls

egg

larva pupa

butterfly

changeSeason()

changeSeason()hatch()

suckHoney()

eatLeaves()

Page 6: © 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a traffic light! – here’s the spec: Have a column of two circles.

© 2006 Pearson EducationDesign Patterns

6 of 20

State Pattern

• Defines way of changing object’s behavior at run-time according to state of its properties

• Delegate response to a separate object that represents a state in state diagram– state knows how to handle message– just change state behavior

• Advantages:– makes primary class more flexible

• can change primary class’ behavior at run-time

• Disadvantages:– must design a new class hierarchy to represent

states– too much delegation can be confusing

Page 7: © 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a traffic light! – here’s the spec: Have a column of two circles.

© 2006 Pearson EducationDesign Patterns

7 of 20

Understanding TrafficLight’s State

• In what states can TrafficLight be?– when state is GoState, switch to StopState– when state is StopState, switch to GoState– can only change between two states — toggle

• What causes TrafficLight’s state change?– changes whenever button is pressed (stimulus)– transition occurs when change() method is sent to TrafficLight (response)

• So each state knows which state is next– can make getNextState() method that returns

the other state– TrafficLight starts in StopState

• so that when button is pressed, light turns green– no real final state

GoStateStopState

Turn TrafficLight to GoState

Turn TrafficLight to StopState

Page 8: © 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a traffic light! – here’s the spec: Have a column of two circles.

© 2006 Pearson EducationDesign Patterns

8 of 20

Implementing a Simple State Pattern

• State Pattern means that:– we have different states that respond to the same

methods in different ways (POLYMORPHISM!)

• Let’s define state superclass:– generalizes methods for its subclasses (each

particular concrete state) to follow

• First, revisit class diagram for TrafficLight object, with more details– TrafficLight contains LightChangeButton

and LightState– LightChangeButton and LightState know

about TrafficLight that contains them

TrafficLight

LightState Light LightChangeButton

Page 9: © 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a traffic light! – here’s the spec: Have a column of two circles.

© 2006 Pearson EducationDesign Patterns

9 of 20

Implementing a Simple State (cont.)

• Note, according to state pattern:– TrafficLight DOES NOT CARE what state it’s in!

• TrafficLight just knows:– what the state can respond to (through the LightState superclass)

– about the particular current state (i.e., has a reference to it) so that it can delegate to it

• In this case, contained instances need a reference back to object containing them

• Note, these implementation details were not reflected in our State Diagram– it models only features pertinent to changing

behavior

Page 10: © 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a traffic light! – here’s the spec: Have a column of two circles.

© 2006 Pearson EducationDesign Patterns

10 of 20

Implementing State Hierarchy

• States must be able to be used interchangeably– TrafficLight can be in two different states

• one state turns light green when button pressed• one state turns light red when button pressed

– each state must be able to switch to other one

• Use inheritance and polymorphism– generic superclass sets policy for subclasses to fill in

• can handle() response as appropriate• can getNextState() to change which state will

handle next response– concrete state subclasses define actual behavior

(but add no additional behaviors)– then TrafficLight will hold reference of generic

superclass’ type that actually refers to state subclass

Page 11: © 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a traffic light! – here’s the spec: Have a column of two circles.

© 2006 Pearson EducationDesign Patterns

11 of 20

LightState Superclass

• Implementing the abstract superclass– each state needs to know about the TrafficLight

it affects– handle() and getNextState() are abstract

• Why have protected instance variable?– subclasses need to have access to traffic light– protected because all subclasses need access

• TrafficLight contains a LightState

• Note: LightState does not contain TrafficLight, but only references it

package Demos.PatternsLecture.TrafficLight;

abstract public class LightState {

protected TrafficLight _trafficLight;

public LightState(TrafficLight light) {

_trafficLight = light;

}

abstract public void handle();

abstract public LightState getNextState();

} // end of class LightState

Page 12: © 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a traffic light! – here’s the spec: Have a column of two circles.

© 2006 Pearson EducationDesign Patterns

12 of 20

GoState Subclass• uses _trafficLight reference to call go()• returns reference to a new StopState

• Why is _trafficLight a protected instance in LightState superclass?– _trafficLight is reference to TrafficLight that

contains this state– all states need to communicate with that light– LightState superclass is abstract and does not know how

to do the work (I.e. handle() and getNextState())• only subclasses can, in their own way, do the work, so they

need access to _trafficLight

package Demos.PatternsLecture.TrafficLight;

public class GoState extends LightState {

public GoState(TrafficLight newTrafficLight) { super(newTrafficLight); }

public void handle() { /** * Note: _trafficLight is a protected variable * in LightState superclass, thus accessible * here. */ _trafficLight.stop(); }

public LightState getNextState() { return new StopState(_trafficLight); }} // end of class GoState

Page 13: © 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a traffic light! – here’s the spec: Have a column of two circles.

© 2006 Pearson EducationDesign Patterns

13 of 20

StopState Subclass

• This one is almost the same– uses _trafficLight reference to stop()– returns reference to a new GoState

• Very similar to GoState, but cannot factor anything else out– same constructor, but cannot inherit constructors– handle() differs in one method in both classes– getNextState() also differs only in one method– this phenomenon is common in small helper classes

like states

package Demos.PatternsLecture.TrafficLight;public class StopState extends LightState {

public StopState(TrafficLight newTrafficLight) { super(newTrafficLight); }

public void handle() { _trafficLight.go(); }

public LightState getNextState() { return new GoState(_trafficLight); }} // end of class StopState

Page 14: © 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a traffic light! – here’s the spec: Have a column of two circles.

© 2006 Pearson EducationDesign Patterns

14 of 20

Implementing TrafficLight

• What are properties of TrafficLight?– contains a LightChangeButton and Lights– uses state objects to determine response to change() message

• What value should variables have initially?– state can be either StopState or GoState– spec says light should go() first time LightChangeButton is pressed

– so StopState should be first state

public class TrafficLight extends JPanel { private Light _top, _bottom; private JButton _lightChangeButton; private LightState _state;

public TrafficLight() { super( new GridLayout(0, 1) ); _top = new Light(); _bottom = new Light(); _lightChangeButton = new LightChangeButton(this); this.stop(); _state = new StopState( this );

this.add(top); this.add(_bottom); this.add(_lightChangeButton); this.add(new QuitButton()); } // continued

Page 15: © 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a traffic light! – here’s the spec: Have a column of two circles.

© 2006 Pearson EducationDesign Patterns

15 of 20

Implementing TrafficLight (cont.)

• Want change() method to delegate its response to current state, then transition to next state– call _state’s handle() method to get response– call _state’s getNextState() method to find

next state

// continuation of class TrafficLight

public void go() {

_top.setLight(Color.black);

_bottom.setLight(Color.green);

}

public void stop() {

_top.setLight(Color.red );

_bottom.setLight(Color.black);

}

public void change() {

_state.handle();

_state = _state.getNextState();

}

} // end of class TrafficLight

Page 16: © 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a traffic light! – here’s the spec: Have a column of two circles.

© 2006 Pearson EducationDesign Patterns

16 of 20

TrafficLight Explanation

• How does this work?– Initially, _state.handle() switches light to green– then _state.getNextState() returns GoState– so _state = state.getNextState() replaces

current state (StopState) with new state (GoState)

– next time _state.handle() is sent, it will make traffic light red.

– thus, change() toggles traffic light’s current state

Page 17: © 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a traffic light! – here’s the spec: Have a column of two circles.

© 2006 Pearson EducationDesign Patterns

17 of 20

LightChangeButton

• Now we are done with the hard stuff– just need to define LightChangeButton, Light, and Frame

• LightChangeButton is simple:– just get reference to TrafficLight and create an inner

listener class to tell the TrafficLight to change on actionPerformed

public class LightChangeButton extends JButton {

private TrafficLight _light;

public LightChangeButton(TrafficLight light) { super("Change" ); _light = light;

this.addActionListener(new LightChangeListener());

}

private class LightChangeListener implements java.awt.event.ActionListener {

public void actionPerformed( java.awt.event.ActionEvent e) {

_light.change(); } }}

Page 18: © 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a traffic light! – here’s the spec: Have a column of two circles.

© 2006 Pearson EducationDesign Patterns

18 of 20

Light

•Light class is really just an ellipse– but need a DrawingPanel to contain it– Light class is DrawingPanel that encapsulates ColorEllipse

– provides methods for the changing the ellipse’s color

package Demos.PatternsLecture.TrafficLight;public class Light extends JPanel {

private gfx.ColorEllipse _ellipse;

public Light() { super(null, true); this.setDimension(

new java.awt.Dimension(200, 200)); this.setBackground(java.awt.Color.white); _ellipse = new gfx.ColorEllipse(this); _ellipse.setSize(this.getSize().width,

this.getSize().height); _ellipse.setColor(java.awt.Color.black); }

public void setLight(java.awt.Color color) { _ellipse.setColor(color); // only time this panel needs to repaint, // so do it here. this.repaint(); }

} // paintComponent() elided

Page 19: © 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a traffic light! – here’s the spec: Have a column of two circles.

© 2006 Pearson EducationDesign Patterns

19 of 20

Frame

• Same as almost every other JFrame

package Demos.PatternsLecture.TrafficLight;

public class App extends JFrame {

private TrafficLight _trafficLight;

public App() { super(“Traffic Light”); this.setDefaultCloseOperation(EXIT_ON_CLOSE);

_trafficLight = new TrafficLight(this); this.add(_trafficLight);

this.pack(); this.setVisible(true); }

public static void main( String[] argv ) { App app = new App(); }

} // end of class App

Page 20: © 2006 Pearson EducationDesign Patterns1 of 20 A Final Example: A Traffic Light Let’s model a traffic light! – here’s the spec: Have a column of two circles.

© 2006 Pearson EducationDesign Patterns

20 of 20

Review of State Pattern

• Generic structure of State Pattern:

• Context represents our TrafficLight– public method request() is handled by state• request() represented by our change()

– AbstractState subclasses handle request and then change context’s state to next with getNextState()

– our _state references GoState or StopState

• AbstractState represents LightState– what if we wanted to generalize this to models with

multiple transitions from a state?• have multiple handle() methods or give more

information to both methods (PARAMETERS!)

Context

request() {_state.handle();}

AbstractState

handle()getNextState()

ConcreteStateA

handle()getNextState()

ConcreteStateB

handle()getNextState()