Professional Documents
Culture Documents
Luca Vigan
Dipartimento di Informatica Universit di Verona
1 / 21
2 / 21
How are we going to get from that state diagram or actual code? Heres a quick introduction to implementing state machines:
1. First, gather up your state:
a. b. c. d. No Quarter Has Quarter Out of Gumballs Gumball Sold
3 / 21
2. Next, create an instance variable to hold the current state, and dene values for each of the states:
/ / each s t a t e r e p r e s e n t e d as a unique i n t e g e r : f i n a l s t a t i c i n t SOLD_OUT = 0 ; f i n a l s t a t i c i n t NO_QUARTER = 1 ; f i n a l s t a t i c i n t HAS_QUARTER = 2 ; f i n a l s t a t i c i n t SOLD = 3 ; / Instance v a r i a b l e t h a t holds the c u r r e n t s t a t e . We l l go ahead and s e t i t t o " Sold Out " s i n c e t h e machine w i l l be u n f i l l e d when i t s f i r s t taken o u t o f i t s box and t u r n e d on . / i n t s t a t e = SOLD OUT;
4 / 21
3. Now we gather up all the actions that can happen in the system:
a. b. c. d. insert quarter eject quarter turns crank dispense
These actions are the gumball machines interface: the things you can do with it. Dispense is however more of an internal action the machine invokes on itself. Invoking any of these actions causes a state transition.
5 / 21
Each possible state is checked with a conditional statement, exhibits the appropriate behavior for each possible state, can also transition to other states.
Luca Vigan (Universit di Verona) The State Pattern Lab. Ing. del SW, 27.05.2011 6 / 21
7 / 21
8 / 21
Look at your code and think about what youll have to do to modify it:
First, youd have to add a new winner state here. That isnt too bad... ... but then, youd have to add a new conditional in every single method to handle the winner state: thats a lot of code to modify... ... turnCrank() will get especially messy, because youd have to add code to check to see whether youve got a winner and then switch to either the winner state of the sold state.
9 / 21
Were going to rework the code to encapsulate state objects in their own classes and then delegate to the current state when an action occurs.
1
First, were going to dene a State interface that contains a method for every action in the Gumball Machine. Then were going to implement a State class for every state of the machine. These classes will be responsible for the behavior of the machine when it is in the corresponding state. Finally, were going to get rid of all of our conditional code and instead delegate to the state class to do the work for us.
10 / 21
First lets create an Interface for State, which all our states implement, and then take each state in our design and encapsulate it in a class that implements the State interface.
11 / 21
12 / 21
To implement our states, we rst need to specify the behavior of the classes when each action is called. Write the behavior of each action in each class...
13 / 21
Think about it from the perspective of a client: if an object youre using can completely change its behavior, then it appears to you that the object is actually instantiated from another class. In reality, however, you know that we are using composition to give the appearance of a class change by simply referencing different state objects.
15 / 21
16 / 21
The class diagrams of Strategy Pattern and the State Pattern are essentially the same, but the two patterns differ in their intent. With the State Pattern, we have a set of behaviors encapsulated in state objects; at any time the context is delegating to one of those states. Over time, the current state changes across the set of state objects to reect the internal state of the context, so the contexts behavior changes over time as well. The client usually knows very little, if anything, about the state objects.
17 / 21
Think of the State Pattern as an alternative to putting lots of conditionals in your context: by encapsulating the behaviors within state objects, you can simply change the state object in context to change its behavior.
19 / 21
20 / 21
21 / 21