Doing the State pattern in Java
As someone who tends to think of objects as โdata structures on steroids,โ it came as quite a shock when Netscapeโs Steve Abell pointed out that an object need not contain any values at all โ it can exist merely to provide behaviors, in the form of methods. This article shows how this concept, along with polymorphism (defined below), can be used to implement the archetypical State pattern in Java โ a pattern that finds many uses in a variety of different contexts.
Separating behaviors into disparate objects makes sense when the separation takes advantage of polymorphism. Polymorphism allows two objects to be treated identically, using the same methods, even though the objects implement these methods in quite different ways. It is this concept of โsame appearance, different behaviorโ that gets the 0 word, polymorphism. (You can tell how important this concept is by the number of syllables the word has!)
Polymorphism works because the classes that implement the same method differently both derive, at some point, from a common superclass. A general program is written that operates on objects of the superclass type. The program is oblivious to the fact that what it thinks of as a superclass object is, in reality, an object that is a member of one of the subclass types. When the program invokes a method defined in the superclass, the method that gets called is actually the subclass method that overrides the superclass version.
Polymorphism allows very general programs to be written for a superclass, letting the subclasses take care of the details. An example of this is a drawing program that can write a loop that processes a list of graphic objects including lines, squares, and circles. It can work from the bottom most graphic object to the top, invoking the draw() method on each object in turn. The drawing program manages the sequence of drawing operations, which depends on which objects are โon top.โ Each object, in turn, is responsible for drawing itself. The program works on objects of type Graphic, knowing that every Graphic object always implements the draw() method. The subclasses Line, Square, and Circle, all derive from the superclass Graphic, and each overrides the draw() method in its own fashion. The program can then be extended by adding an Elipse or Rectangle class. As long as the new classes derive from Graphic, and as long as they implement the draw() method appropriately, the basic drawing program continues to work, unchanged.
(See Philip Bishopโs JavaWorld article, โPolymorphism and Java,โ for more information on this subject.)
The State pattern, described in the book Design Patterns, by Gamma, Helm, Johnson, and Vlissides, Addison-Wesley, 1995 (see Resources for further book information), is an example of a tremendously useful software pattern that takes advantage of polymorphism. (The State pattern is just one of 23 useful patterns contained in that book.) The State pattern uses polymorphism to define different behaviors for different states of an object. It is a valuable pattern to master, because it can be used in practically any sizable application.
The following โprecerpt,โ from The JBuilder Java Bible (due to be published this fall), describes how to implement the State pattern in Java.
Understanding the State pattern
The State pattern is useful when you have an object that can be in one of several states, with somewhat different behavior in each state. For example, when a carโs RPMs are in the โpower band,โ then the carโs acceleration is much quicker than when the revolutions per minute are outside that range. The Car object might have a state variable that indicates โin the power band,โ โbelow the power band,โ or โabove the power band.โ The acceleration characteristics of the car would then depend on its current state.
There are many cases in which an objectโs behavior depends on its current state. For example, when youโre sleepy, itโs hard to think. But when youโre jazzed on coffee and chocolate, it can be easy! The examples go on and on. So itโs worthwhile to have a readily usable State pattern to draw on.
The way the State pattern works is shown in the following diagram:

This diagram shows that the PowerBand class is an abstract class and the Car object contains a PowerBand object. The PowerBand class really acts as a kind of placeholder. Because it is abstract, it is not possible to create a PowerBand variable. Instead, the variable will hold one of the objects created from a subclass of PowerBand.
Each subclass then defines the behavior appropriate to that state. When the Car object receives a request to accelerate, it delegates the request to its state object. The kind of acceleration you get depends on the state the car is in at the time.
Writing a generic state class
Here is the code from State.java, stripped of its comments. In this section, weโll analyze this code to see how it works.
abstract class State {
static State initialState;
static final State state1 = new State1();
static final State state2 = new State2();
protected State() {
if (initialState == null) initialState = this;
}
abstract void stateExit(StateOwner owner);
abstract void stateEnter(StateOwner owner);
}
class State1 extends State {
void stateExit(StateOwner owner) {
}
void stateEnter(StateOwner owner) {
}
}
class State2 extends State {
void stateExit(StateOwner owner) {
}
void stateEnter(StateOwner owner) {
}
}
Analysis
To understand this bit of code, youโll need to take it apart and look at it, piece by piece.
State classes
Taking a high-level overview, you can see three classes:
abstract class State {
...
}
class State1 extends State {
...
}
class State2
extends State
{
...
}
The State class is an abstract class. It provides some basic behavior, but its only real purpose is to be extended to produce one or more โrealโ state classes. In this case, two state classes are defined, State1 and State2. To create additional states, you would copy one of these classes.
Static variables
The State class defines three variables:
abstract class State {
static State initialState;
static final State state1 = new State1();
static final State state2 = new State2();
...
The first variable is the default initial state. The first state that gets created will be stored in that variable, in case the StateOwner object wants to use it. (It doesnโt have to.) The next two variables create the state objects using the classes State1 and State2.
Because these variables are defined as static, they belong to the State class. In other words, they are class variables, which means they belong to the class as a whole, rather than to individual objects. Without the static keyword, they would be instance variables, meaning that each object created using the class (each instance of the class) would have its own variable.
In general, using the static keyword means there is only one copy of the variable for the entire class, no matter how many objects are created using that class. Such variables generally are used for class-wide data, such as a count of the number of objects that are created using the class.
Protected constructors
The next significant part of the State class is the constructor, which saves the first state created as the default initial state. The important feature of the constructor is that it is defined as protected:
protected State() {
if (initialState == null) initialState = this;
}
Because the constructor is protected, it cannot be used by other classes to create new objects. It can only be used by the State class and by those classes that extend the State class.
Since the State class is abstract, only the subclasses have access to the constructor, which is equivalent to making the subclass constructors private. In other words, the subclasses can create themselves using static variables, but they can never be used at run time to create additional objects.
In this case, the abstract State class creates the static variables state1 and state2. The protected constructor forms a โclosed loopโ with these static variables. The creation of the static variable state1 accesses the State1 constructor, which invokes the State constructor, which is protected. The final result is that the state variables can only be created from within the State class and its subclasses. They form a predetermined set that is defined at compile time.
Abstract methods
The last part of the State class defines two abstract methods, stateExit() and stateEnter():
...
abstract void stateExit(StateOwner owner);
abstract void stateEnter(StateOwner owner);
}
Because these methods are defined as abstract, they have no method body. That means they must be implemented by the subclasses that extend the State class. That, fundamentally, is the reason for defining an abstract class in the first place โ to specify the kinds of methods the individual states will provide, and leave the implementation up to them.
The State class says that each state will have two methods, one for when you exit (or leave) a state, and one for when you enter (or arrive at) a state. Although you do not always need both methods, frequently it is helpful to have them. In multiple state systems, the combination of leaving one state and arriving at another can completely define the actions needed for a transition between the two states.
For example, consider the three states Accelerating, Slowing Down, and Stopping, as shown in the following diagram:
The action associated with slowing down might be to press lightly on the brake. The action associated with stopping might be to press firmly on the brake. When leaving the Accelerating state, the action in both cases would be to remove your foot from the accelerator. Only then would you take the action appropriate for slowing down or stopping.
Note: The exit action for the Slowing Down state could also be โremove foot from brake.โ That would allow a transition from slowing down to accelerating even though, for stopping, the foot would be put right back on the brake. In a real-time program, such inefficiency would not be acceptable. But in many applications, such a โtake it away and put it right backโ technique is a useful stratagem that produces a correct result with very simple code. Often, the performance penalty is insignificant compared with the clarity of the result.
Implemented methods
Finally, here is a class that defines one of the actual states:
class State1 extends State {
void stateExit(StateOwner owner) {
}
void stateEnter(StateOwner owner) {
}
}
This class defines the stateExit() and stateEnter() methods so they are ready to be filled in with the behaviors appropriate for the state.
Using the State class
Here is a sample of code for testing the State class:
public class StateOwner {
//Create the object and initialize its state
public StateOwner() {
this.stateVar = State.state1;
stateVar.stateEnter(this);
}
// Set the new state
public void setState(State newState) {
stateVar.stateExit(this);
this.stateVar = newState;
stateVar.stateEnter(this);
}
private State stateVar;
}
In this code, the constructor for the StateOwner class sets up the initial state and calls the entry method for that state.
The setState() method calls the exit method for the current state, sets the new state, and then calls the new stateโs entry method.
Finally, the private variable state stores the current state for the object.
(End of precept)
Final notes
Here are a couple of thoughts on how to use and extend this state pattern.
Encapsulating the state transitions
Using the State class requires calling the stateEnter() and stateExit() methods when the state changes. An alternative implementation would put everything that is currently in the StateOwner class into a new class called (for example), StateType. That way, the StateType object can encapsulate the state-transition behavior. The StateOwner class can then create a StateType object, calling the setState() method to change states. The object then can take care of doing the state transitions whenever the state changes. Thatโs what object-oriented programming is all about!
In some cases, it is appropriate to do the state changes when the new state is the same as the old state. In other cases, setting the current state to the same value should be a โno-opโ โ that is, it should have no effect. For such cases, the setState() method can compare the new state against the current state and simply return if they match.
Enumerating the possible states
It may be desirable occasionally to enumerate all of the possible states. For example, you might want to write a loop, where the loop index is one of the possible states. Itโs not common that you want to do such a thing, but itโs possible. To do this, the various State objects need links to one another, and the State class needs to define a method that returns an Enumeration object, which lets you iterate over the linked list of defined states. The mechanisms for doing that are defined in โCreating enumerated constants in Java.โ
Conclusion
The State pattern is a good addition to your bag of programming tricks, because it is so useful. There are many ways to implement the actions associated with state transitions. It is possible to define actions as part of transition-objects, or define them as part of state-objects. You can have behaviors that occur when exiting a state, when entering a state, or both. The emerging Unified Modeling Language standard (UML) allows for all three. In this article, you learned how to use the fundamental O-O concept of polymorphism to implement a version of the State pattern that associates actions with states and that allows both state-exit and state-enter actions. You also saw how to completely encapsulate the state transitions in a state object that can be owned by a higher-level โcontainingโ class.


