The State Design Pattern vs. State Machine

How to use the State Design Pattern when compared to State Machines, Switch statements, or If statements.

Introduction

This article and the accompanying example source code explain and demonstrate the State Design Pattern and how it can be used to make your code easier to maintain
as well as easier to read, especially when compared to implementing State Machines.

Background

Design patterns in software development are an essential tool to excellent software creation. Being able to identify patterns while observing source code, is an essential skill that is acquired over a period of years of object oriented software development practices. Over the years, I’ve seen patterns being implemented that only have the name of the pattern in file names but hardly represent the actual pattern the way they were intended to be used. Also, I have seen state machines being used instead of state design patterns at the costs of horribly complicated software that is hard to maintain. There is no reason to use state machines anymore when you are using an object oriented programming language.

One of the best sources about software design patterns is the “Design Patterns: Elements of Reusable Object-Oriented Software” book by the Gang of Four. Still, it is the bible of design patterns after all these years. There are many other sources and books but the blue book by the Gang of Four is the fundamental one that all seasoned architects and developers should have mastered.

Design patterns are programming language neutral. What they convey and solve are concepts that can be applied in any object oriented programming language such as C#, C++, Delphi, Java, Objective-C, etc. It is these concepts that one should master. Once the concepts are mastered, it is fairly straightforward to identify opportunities to use and apply them. At that point, it is simply a matter of language syntax.

In this article, I will discuss the State Design Pattern. I will discuss the state design pattern on how it can be used in a fairly complex scenario and demonstrating this with sample C# code. I will also discuss using the state design pattern instead of using a state machine. I will not go into the details of how to create state machines, rather I will concentrate on the much more modern State Design Pattern. I picked a complex scenario because I believe that a more complex scenario can teach several things at once. It will demonstrate the combination of different scenarios and answer more questions this way.

The State Design Pattern

I would summarize the State Design Pattern as follows:

“The state design pattern allows for full encapsulation of an unlimited number of states on a context for easy maintenance and flexibility.”

From a business side of things, this is worth a lot of money. There is no reason anymore NOT to use the state design pattern even in very simple state scenarios. You can get rid of switch statements (C#), for example. It buys you flexibility because you won’t be able to predict the future and requirements changes (I’m pretty sure about that).

The State Design Pattern allows the context (the object that has a certain state) to behave differently based on the currently active
ConcreteState instance.

Let’s take a closer look into the parts that make up the state design pattern.

Context Object

Context is an instance of a class that owns (contains) the state. The context is an object that represents a thing that can have more than one state. In fact, it could have many different states. There is really no limit. It is perfectly fine to have many possible state objects even into the hundreds. It is coming to have context objects with only a handful of possible states, though.

The Context object has at least one method to process requests and passes these requests along to the state objects for processing. The context has no clue on what the possible states are. The context must not be aware of the meaning of these different states. It is important that the context object does not do any manipulation of the states (no state changes). The only exception is that the context may set an initial state at startup and therefore must be aware of the existence of that initial state. This initial state can be set in code or come from an external configuration.

The only concern that the context has is to pass the request to the underlying state object for processing. The big advantage of not knowing what states the context could be in is that you can add as many new states as required over time. This makes maintaining the context super simple and super flexible. A true time saver and a step closer to being rich beyond your wildest dreams (almost).

State

The State class is an abstract class. It is usually an abstract class and not an interface (IInterface). This class is the base class for all possible states. The reason why this class is usually an abstract class and not an interface is because there are usually common actions required to apply to all states. These global methods can be implemented in this base class. Since you can’t do any implementation in Interfaces, abstract classes are perfect for this. Even if you do not have any initial global base methods, use abstract classes anyways because you never know if you might need base methods later on.

The State class defines all possible method signatures that all states must implement. This is extremely important to keep the maintenance of all possible states as simple as possible. Since all states will implement these methods signatures and if you forget to implement a new method, the compiler will warn you at compile time. An awesome safety net.

ConcreteState

The ConcreteState object implements the actual state behavior for the context object. It inherits from the base State class. The
ConcreteState class must implement all methods from the abstract base class State.

The ConcreteState object has all the business knowledge required to make decisions about its state behavior. It makes decisions on when and how it should switch from one state to another. It has knowledge of other possible ConcreteState objects so that it can switch to another state if required.

The ConcreteState object can even check other context objects and their states to make business decisions. Many times, an object may have more than one context object. When this happens, a
ConcreteState object may need to access these different states and make a decision based on active states. This allows for complicated scenarios but fairly easy to implement using the state design pattern. You will see an example later in this article that shows multiple context objects and their states and the need to work together.

The ConcreteState object also is capable of handling before and after transitioning to states. Being aware of a transition about to happen is an extremely powerful feature. For example, this can be used for logging, audit recording, security, firing off external services, kicking of workflows, etc. and many other purposes.

The ConcreteState object allows the full use of a programming language when compared to state machines. Nothing is more powerful in abstract logic and conditionals coupled with object orientation as a computer programming language compared to state machines and their implementations.

As you add new methods to the abstract base class over time, each ConcreteState class will need to implement that method. This forces you to think from the point of view of the current state.

“How should state ConcreteStateA react when this method is called?”

As you implement the behavior for a method, you can be rest assured that this is the only place in the entire system that will handle this request when
ConcreteStateA is the active state. You know exactly where to go to maintain that code. Maintainability is king in software development.

Summary

To summarize, you will need a context and a few states that ideally derive from an abstract base class to create a flexible state solution.
If you got switch statements or a lot of If statements in your code, you got opportunities to simplify by using the state design pattern.
If you are using state machines, you got an awesome opportunity to simplify your code and safe time and money. Just do it!

Example

The example I created demonstrates the use of the State Design Pattern and how it can be used with multiple context objects working together. It is a fictitious hardware device with a door.

The device can be powered on or off. Specifically, the device has an operations mode that can be in the following states:

Idle

Busy

Powering Down

Powering Up

The door represents a physical door on the device. The door can be in the following states:

Opened

Closed

Locked

Unlocked

Broken

To make it a little more complicated, the device can be in different hardware configurations. These configurations can be changed at run-time of the device.
The following configurations are available:

Production Configuration

Test Configuration

The operation of the device depends on the different individual states as well as a combination of the states listed above. The more combinations that are possible, the more complicated it would be to maintain this using traditional Switch or If statements. You could use a state machine as well but it will not buy you the flexibility and ease of use when compared to the state design pattern. Feel free to add brand-new states and try to experiment with it.

Breaking it Up

No matter how complicated software projects are, the way to tackle them successfully is to break them up. This is especially true in object oriented software development. Breaking things up into smaller, manageable pieces allows a focused effort in understanding the problem domain. It is coming to zoom into the smaller parts and then zoom back out again to a 10,000 foot view and vice versa. You do this many times. Look at the big picture, then break up the picture into smaller parts, look at the smaller part and so forth. Object orientation is a natural fit to model real-life scenarios that contain things, people, processes and their behaviors to interact with each other.

Let’s break up the things that we do know in this example. It looks like we have three things:

Device

Door

Configurations

Behavior

It is important to recognize that there is most likely a certain behavior between these things. This behavior is probably driven by certain business or operational rules. The power of object orientation is being able to capture this behavior inside classes. Since an object generally consists of roughly 50% data and 50% behavior, we must take care of the behavior part of objects. Over time, this behavior might change because requirements may have changed. Again, this is where object orientation shines when it is done correctly.

So, we can assume that Device is on its own. It represents a physical device from the real world. The door is part of the device and can’t live on its own.
The device has a door. So, it looks like we have this:

Device with a Door

Configurations

We also have a set of configurations. These configurations change the operation of the device but are not necessarily part of the physical device. So, we could model configurations on a class by itself. However, since we know that a device can be either in a test configuration or a production configuration, these actually represent operational states. We also know that certain operations or states of the door might behave differently based on the current configuration. So, there is no need to create a separate configuration class and instead model the configurations as states themselves. If we decide to add another type of configuration later on, it will be easy to add.

We have two major parts: Devices and their configurations. We will model each part with their own class. The
Device class will contain a Door class (Device has a door):

Both the Device and Door classes inherit from the
DomainObject class. The DomainObject class is a convention that I’ve accustomed to use over the years. A base domain object class contains behaviors and features that are shared across all domain objects. For example, my
DomainObject class usually implement a read/write string Name property. This name can also be optionally passed into the constructor. When you model real world things, it is very common that these things have names. So, I end up having a Name property in my base
DomainObject class. You will see later how this is used.

Code

Let’s start writing some code and implement everything. The example we are building is a console application that sets several states to test the Device’s behavior. It will look like this once the output displays on the screen:

First, let's create the DomainClass, the base class for all domain objects.

The DomainObject class implements a Name property of type string that allows you to conveniently give an object a name since most objects in real life have names. This is the base class for all domain classes.

Next, we implement the Device class. The Device class contains a
Door object. In this scenario, the Device class is the context (the owner) to the operations mode and the possible configurations. The operations mode is represented with the
ModeState class. The different kind of configuration states are kept track in the
ConfigurationState class.

The Initialize() method is used to setup the different kind of states for the current instance of a device. This is the place where the context (the Device) now needs to be aware of what states are actually available. Notice also that within the method we are setting the operations mode to Powering Up and at the end of the method we set it to Idle.

///<summary>/// The Device class is the owner of the different states
/// that the Device can be in. The Device is also the
/// owner of actions (methods) that can be applied to the
/// states. In other words, Device is the thing we are
/// trying to manipulate through outside behavior.
///</summary>publicclass Device : DomainObject
{
// Device has a physical door represented by the
// Door class.
private Door _door;
// Device only knows about generic actions on
// certain states. So, we use the base classes of
// these states in order execute these commands.
// The base classes are abstract classes of the
// states.
private ConfigurationState _configurationState;
// The current mode that the device is in.
private ModeState _modeState;
public Device(string name) : base(name)
{
Initialize();
}
public Device()
{
Initialize();
}
privatevoid Initialize()
{
// We are starting up for the first time.
_modeState = new ModePowerUpState(this);
_door = new Door(this);
// The initial configuration setting for the
// device. This initial configuration can come
// from an external configuration file, for
// example.
_configurationState = new ProductionConfigurationState(this);
// The door is initially closed
_door.DoorState = new DoorClosedState(_door);
// We are ready
_modeState.SetModeToIdle();
}
public Door Door
{
get { return _door; }
set { _door = value; }
}
public ConfigurationState Configuration
{
get { return _configurationState; }
set { _configurationState = value; }
}
public ModeState Mode
{
get { return _modeState; }
set { _modeState = value; }
}
}

The ModePowerUpState class is one of the ConcreteClass implementations of the State Design Pattern. Let’s take a closer look
at how it is implemented.

The first thing to notice is that it inherits from the ModeState abstract base class. This would be the abstract base class for all mode states in state design pattern. The following operation modes are possible for this device:

Powering Up

Powering Down

Busy

Idle

Each of these possible modes are represented as individual ConcreteState classes.

An important fact is that one of the constructors takes an abstract representation of a mode:

public ModePowerUpState(ModeState modeState)

This constructor is very important since it will allow the object to set the context (the owner) by using polymorphism. Setting the owner via:

this.Device = modeState.Device;

allows the pass in different kind of modes and always have access to the context. Once we have access to the context, this instance can now manipulate the Device’s mode. It can also manipulate any other properties or call methods on the Device.

Since the ModePowerUpState class inherits from the abstract
ModeState class, it needs to implement all abstract methods that are declared in the
ModeState class. The abstract ModeState class declares the the following abstract methods:

This Fix() method is meant to be called by any of the derived ConcreteState classes in order to bring the Door
to an initial Closed state (when it has been been fixed after it was broken).

When you download this example source code, you can take a closer look at all files. But, let’s take a look at the more interesting
DoorUnlockedState concrete state class:

publicclass DoorUnlockedState : DoorState
{
public DoorUnlockedState(DoorState doorState)
{
Initialize();
this.Door = doorState.Door;
}
public DoorUnlockedState(Door door)
{
Initialize();
this.Door = door;
}
privatevoid Initialize()
{
Name = "Unlocked";
}
publicoverridevoid Close()
{
// We can't close an already locked door.
}
publicoverridevoid Open()
{
// Can't open a locked door.
}
publicoverridevoid Break()
{
// To simulate production vs test configuration
// scenarios, we can't break a door in test
// configuration. So, we need to check the
// Device's ConfigurationState. We also want to
// make sure this is only possible while the
// device is Idle.
//// Important:
// ==========
// As you can see in the If statement, we can
// now use a combination of different states to
// check business rules and conditions by simply
// combining the existence of certain class
// types. This is allows for super easy
// maintenance as it 100% encapsulates these
// rules in one place (in the Break() method in
// this case).
if ((this.Door.Device.Configuration is ProductionConfigurationState) &&
(this.Door.Device.Mode is ModeIdleState))
{
this.Door.DoorState = new DoorBrokenState(this);
}
}
publicoverridevoid Lock()
{
this.Door.DoorState = new DoorLockedState(this);
}
publicoverridevoid Unlock()
{
// We are already unlocked
}
}

Take a close look at the Break() method. This is where it gets interesting and demonstrates the use of more than one set of states that are not related to each other. In this case, the state needs to check that the device is in a certain configuration as well as in a certain operations mode before it can set the door state. In order to access these conditions, the state needs access to both contexts,

Because this scenario only allows to break the door when the device is in a production configuration and the operations mode is idle, both conditions are verified by using the state class definitions:

By simply chaining class definitions in your comparisons, you get clean compile time validations when compared to string or similar comparisons. The code is fairly easy to read and to expand upon.

Remember that one of your goals is encapsulation when you use object orientation. You have one central place to maintain your code for a certain state that you need to modify or when you need to create a brand new state.

Conclusion

Using a State Design Pattern over Switch and If statements and over State Machines is a powerful tool that can make your life easier and save your employer time & money. It’s that simple.

Share

About the Author

Thomas Jaeger is a Solutions Architect and an industry expert for over 24 years in 10 different industries when it comes to software development in general, cloud-based computing, and iOS development. He is a passionate, fanatic, software designer and creator. He lives against the status quo because, in his opinion, creative and innovative solutions are not created following a linear approach but come, in part, from broad experiences in ones life and from an innovative mind.

Comments and Discussions

Too bad there are egotistical idiots like, Sergueis63 and Mercede, who like to chop the heads off others to make their pathetic selves look taller (no doubt they're probably not liked too much at their present jobs, if they're even employed at all! ha!)...

I thought the article was great. Sure, there are other ways to skin a cat, but you gave a nice sample where someone can use this example in certain scenarios...

Mr. Fowler (code smells in agile development) said one can actually overdo decoupling, so whatever the actual solution calls for is whats best in terms of what pattern to use; your example is just fine!

Wow. I will use it within my project. This project embraces just the concepts and issues that I needed to solve. I don't know about getting rich but I will probably now remain sane and on budget. I hope to come back to this post some day and add some entertaining GUI view.No further comments to entertain the OOd.

I worked on this piece of pathetic code where the author did not understand the concepts himself and he wrote this article to confuse others with his convoluted and limited (mis)understanding. Here is the same "device with a door" state machine. Please comment if you think it is better and easier to understand than the original one:

Whoooeeee you're a rude bastard. If you have some problems with the article why not state them instead of making stupid, general statement (and attacking the author who I thought did a great job). Also just rewriting the code without explaining anything is a useless exercise.

Are you saying that the domain class should have all of its code broken up into modules that can be passed in to the state objects? Why should the state objects get a reference to the domain object itself so it can act upon the domain's members?

For example, lets say my domain class is Player. Player can be logged in or logged out. To log in, a Player is presented with prompts for username and password and then sends responses to the system. Would the Player class have a Login object that handles all the login code as well as a Login_State object? Or would the Player object itself know how to login and then have only a login_state object that then makes calls back up to the Player to handle the login?

It's actually quite simple. The reason why state objects get a reference to a domain object (the context) itself is to be able to modify the context state without the domain object having to know about all possible states at the time or any possible future states in the future. This gives the flexibility to have two or many more possible states without having to make any changes to the context.

In your example, the Player object can only be in two states, LoggedIn and NotLoggedIn. If this is the only range that you think a player can be in, it might be better to use a boolean. One of the reasons you would would use state objects is to encapsulate the complexity of changing state. This change, might involve complex business rules that are outside of the responsibility of the domain object. The logging in process might be a complex process in your case and may warrant separate state objects (LoggedIn, NotLoggedIn). It depends.

It depends on the exact use cases. For example, if you are using microservices in your backend and have Application Services that delegate the domain logic into Domain Event and Domain Services, then I can see the authentication and authorization of the log in process being delegated into a Domain Service inside your Domain Model (Domain Driven Design).

Anyways, it really depends on the use cases and what kind of backend architecture you have or plan to have.

1. There is more than one state machine involved: one for doors, one for devices, pne for configurations (?). This is too confusing for an illustrative example.

2. The state machines are implemented slightly differently: the door states handle operation requests like Close(), while the mode state class (BTW, why isn't it called DeviceState?) allows to change states explicitly: there is no ModeState.PowerUp(), but there is ModeState.SetModeToPowerUp().

3. There are too many dependencies between classes:- each ModeState knows about parent Device, and can change its state- each ModeState knows about every other ModeState- door states know about each other, about the Door, about the Door's Device, and some even query Device's Mode and behave differently based on what they found. In my book the latter is really poor OO design.

4. The code does not implement the pattern correctly. The class diagram at the beginning of the article shows that Context should know about States, but not vice versa.

A better solution would be:

1. Reduce the number of state machines involved. If this is not an option, make implementation style such as naming conventions as uniform as possible.

2. Remove reference to Device from ModeState and reference to Door from DoorState.

3. Have methods like Close(), Open(), Break() return an instance of new state (possibly just "this"), and then the Door will do things like _doorState = state.Close();

4. Remove a link from Door to Device. If door's behavior depends on device state, add more door states.

And last, but not least: let's be civil to each other. "Your comment clearly shows that you have a severe lack of understanding..." is not how civilized educated people conduct constructive discussion.

This is a good example on what to avoid in OO design: total interdependencies between classes, the code is very hard to maintain. A lot of unrelated stuff about "virtues of OOP" instead of concrete and precise explanations. The resulting design in no better than a bunch of switch statements (actually, it's worse because it's longer).

Your comment clearly shows that you have a severe lack of understanding the principles if object orientation. If you had any kind of valuable feedback to provide, you should read the Gang of Four and start learning the principles of the OO concepts. Your feedback clearly is of no use to anyone but only to demonstrate your novice start as a programmer with all the problems a beginner struggles with. I would recommend reading about OO and start putting it to practice. The State Design Pattern comes straight from the Gang og Four. Maybe you should contact the authors as well, maybe the Gang of Four made a mistake in publishing their vast experience? I don't think so.

My comment clearly shows my 26+ years of commercial software development including 22 years of OOP/OOD.

1. In Gang of Four's book, State objects don't hold reference to context. In your case, they hold it.2. In Gang of Four's book, concrete State classes don't have direct access to context internals. Instead, they just call context methods. In your case, they do have direct access to context's fields. Moreover, they have access to fields of context's fields.3. Because of 1 and 2, in Gang of Four's book, state objects are stateless and decoupled from context as much as possible. In your case, it's just the opposite.4. The only time you used word "polymorphism", you did it wrongly. The case where you mentioned it is not polymorphism.5. Default constructors if DomainObject and Device should call version with String parameter. By doing that you (a) don't need to repeat constructor body and (b) you initialize Name variable with some default value (but not leave it uninitialized as in your case).6. Still, State design pattern is an implementation of State Machine. So, I don't really understand how you can compare them with word "versus".

1,2. Gang of Four's book clearly state on page 307 and I quote: "A context may pass itself as an argument to the State object handling the request. This lets the State object access the context if necessary." State objects do have access to public properties of the context and this is important if handling the state transitions are required. So, please re-read.

3. Because of the importance of State objects being able to have access to public properties and methods of the context, your point is not logical.

4. It clearly is polymorphism.

5. True, it was a simple example.

6. Completely wrong. State Design Pattern has nothing to do with a State Machine. Gang of Four book page 308 clearly spell this out in the implementation section. Please re-read!!!

@Thomass: You clearly misunderstood the pattern. The functions in the abstract state are the functions events or actions that are performed on the object for which you hold the context. The actions after being performed or events after happening determine state change. they are not the functionalities that states have to provide.

the problem is you don't want to listen to anyone at all because you think everyone else is an idiot with the sole intention of trashing your piece of art (= sh*t)!

Your comment clearly shows that you have a severe lack of understanding the principles if object orientation. If you had any kind of valuable feedback to provide, you should read the Gang of Four and start learning the principles of the OO concepts. Your feedback clearly is of no use to anyone but only to demonstrate your novice start as a programmer with all the problems a beginner struggles with. I would recommend reading about OO and start putting it to practice. The State Design Pattern comes straight from the Gang og Four. Maybe you should contact the authors as well, maybe the Gang of Four made a mistake in publishing their vast experience? I don't think so.

I like this article because it's not only about the main topic but you provide us some information why you do something as you do itFor example, for new developers its a interesting thing why you use your DomainObject as base object.

I gave you 4 stars simply because more programmers need to be aware of how to properly implement state, in any manner at all, and articles like this contribute to that end. But I took off a star because the pattern really is not anything "new", as are many things in software architecture. I have used a controlling State node that controls many ConcreteState nodes in many of my applications. The most recent being a large truck diagnostic and estimating service application. By using this pattern it enabled me to allow any number of different truck service bays to be serviced simultaneously simply by instantiating new instances of the ConcreteState class. Allowing a user to perform multiple tasks without having any single task "step on and corrupt" any other task. My integration layer only needed to "navigate" the primary State node in your diagram. I wrote the code to be totally agnostic to any particular platform and so I was able to port the same kernal to WCF, IIS and believe it or not batch processes. One kernal for smartphones, browsers, apps, and other integrated consuming applications. I may have different terminology for example what I called "Stateful Kernals" you called "Concrete State" but its all the same. I've been totally satisfied with this pattern because it really does provide a level of extensibility in an application that allows the code to stand the test of time through much maintenance, even by crappy programmers. The key is to simply make sure the programmers are pushing logic down into the concrete state objects and not letting that creep up into other layers, or God forbid getting into UI. My example used instances of a single concrete state class, but I also implemented a more polymorphic state by instancing different classes for different user audiences, service advisor, manager, manufacturer, etc. The main "beauty" of this in the end is that its so flexible and very dependable separation of concerns can be achieved, meaning a users state doesnt start to corrupt itself as a singleton state model would eventually.

Fantastic. Another great example on how powerful the state design pattern can be if it is used by people like yourself that understand the principles of object orientation. Thank you for your feedback and great example. I appreciate it.

I believe that your use of the phrase "State Machine" is wrong. The State Design Pattern and the implementation of it that you provided are one of many ways to implement a state machine, and are not some other thing. I think that you were trying to differentiate the State Design Pattern from switch/case and table driven state machine implementations, but by saying that the State Design Pattern is better than the State Machine you have confused the subject. Since the State Design Pattern is a subset of the possible State Machine designs all general state machine theory (Finite State Automaton, Push Down Automaton, and Turing Machine) still apply, and anyone solving a problem with a State Design Pattern would be on much better ground if they were not turned off to reading resources about State Machines because you told them that they were inferior. Designing good state transitions and knowing about the limitations and pitfalls of this type of program (computability and infinity recursive states) are still more important to a correct implementation. My guess is that you know this intuitively, but have just chosen your wording poorly.It is also worth mentioning that when generating state machines programatically (such as language recognizes like lex, yacc, ...) tables (or state graphs) are usually the easier to generate and since the complexity of reading the code is primarily limited to the language specification source file and not the actual state machine code in a general purpose language this method should be more easily read and understood.

Until now i understood the state pattern in this way that i encapsulate the state transition logic for one state in a class. If there is a new state i write a new class which derives from my base class and use it.

You implement all transitions as abstract methods in the base class. So if you have to add a new state you will enhance your abstract base class by a new abstract method and therefore you have to enhance each derived class. The implementation also leads to duplicate code as you can see in DoorState.Break(). You have to repeat the code in the other state classes.

Yes, I implement abstract base methods. The pattern does describe of having these methods in the base class. I look at it like this: If you implement these base methods as abstract, it will force you to at least have an empty stub method in each derived class. This is easy to do with Visual Studio's code completion by implementing the missing method(s) for you. If you use ReSharper, it's just a click away. My point is though that it will force you to think from the point of view of that particular state at the time a method is called. In my experience, the more states you have, the easier this will get actually because I won't miss any states and how they show react when states need to switch and act upon those methods. Your milage may vary but it has helped me in the past.

Regarding duplicate code, it really depends from the point of view of the state. If the states have similar code or can act the same way you may use a common code base although I would be careful in doing this. It's a balance between encapsulation and convenience for the developer. I would always opt for encapsulation because I know it will pay off in the long run.