Table of Contents
What is the State Pattern?
The definition of the State Pattern from both Design Patterns: Elements of Reusable Object-Oriented Software and Head First Design Patterns: A Brain-Friendly Guide is
The State Pattern allows an object to alter its behavior when its internal state changes. The object will appear to change its class.
State Pattern Class Diagram Explained
The above class diagram represents the State Pattern in its simplest form. We can see there is a Context class that has a State interface to any given concrete state class (ConcreteStateA and ConcreteStateB). Context also implements a public member Request() method that delegates its behavior to its current State. This provides a robust solution to implement different behaviors based on an object’s state. Additionally, it is well encapsulated and easily extendable if new states need to be added. Also, adding a state doesn’t require the behavior of the other states to change, thus supporting the open/closed principle.
State Pattern Example
To further demonstrate what the State Pattern is all about, I created a little Music Player example with some of the simplest requests and state transitions a music player requires. Consider a MusicPlayer object that acts as our Context class. It supports requests of Play(), Pause() and Stop(). It will delegate the behaviors of these requests via it MusicPlayerState member which acts as the MusicPlayer’s current state. We have three derivations of the MusicPlayerState base class. They are PlayingState, PausedState and StoppedState. Each overrides the methods of their base class that require specific behavior based on current state. For PlayingState, Pause() and Stop() are overridden. For PausedState, Play() and Stop() are overridden. Finally, StoppedState overrides just the Play() method.
Example written in C++
So we have our design finished. Let’s take a look and see what our implementation will look like.
MusicPlayer.h
MusicPlayer.cpp
MusicPlayerState.h
MusicPlayerState.cpp
PlayingState.h
PlayingState.cpp
PausedState.h
PausedState.cpp
StoppedState.h
StoppedState.cpp
MusicPlayerTest.cpp
Here is the output of this program.
changing from Stopped to Playing state
changing from Playing to Paused state
changing from Paused to Stopped state
All the code for this post can be found here
Benefits of the State Pattern
There are a few benefits of the State Pattern. Most noteworthy, it’s an extendable design as it allows to easily add new states without the need to change other state objects, thus supporting the open/closed principle. As a result, the pattern can potentially have many state classes. This may not be ideal but it would potentially avoid complex conditional statements if states were represented by data values. Another benefit of the State Pattern would be that state changes would be more explicit while it would be less so if states were represented by one or more data value assignments. Finally, the State Pattern may allow for State objects to be shared. This would depend on whether or not the State objects contain internal instance variables. If none exist, the object is deemed shareable.
Recommended Resources
Here are some resources I recommend for more information on the State Pattern
Head First Design Patterns: A Brain-Friendly Guide
Design Patterns: Elements of Reusable Object-Oriented Software
In Closing
There you have it. If you followed along, I hope you now have a better understanding of the State Pattern. Please feel free to leave comments and feedback. Much appreciated!