Back to the main site


[Revised] Design Patterns: The State Pattern in C++

This post was revised on the September 17, 2011.

 

So my first attempt at doing the State pattern didn’t go well. But, which the helpful folks at /r/programming I got set back onto the right track again. The end result is something a lot more complex than what I had originally intended but the files are available for download at the bottom of this post for your own perusal.

 

I’m going to use the State pattern in the following scenario: we have a player, be it in an FPS/space-shooter/genre of your choice, who can pick up a shield power-up. So, naturally, when he/she is shot at the shield will absorb the damage. Once the shield has run out the player reverts back to taking damage as normal until they are dead. Under the hood of the Player class we’ll see that is has a single function to take damage and that the behaviour of this function will depend on its internal state variable. This will also be a project in Code::Blocks with multiple files so we’ll also take a very quick look at circular dependencies.

 

This post will assume that you’ve got a firm grasp of Polymorphism (check out my C++ and Java tutorials if you’d like to know more) as well as an understanding of the Singleton design pattern. Now, let us begin.

 

First we’ll take a quick look at a UML diagram to get a feel for how this is going to work.

 

State Pattern Diagram

 

Here we can see that the Player will have an instance of the State class (which is, in fact, an abstract class) as an aggregate. This is what will allow us to change the state variable inside the Player to the State subclasses (Normal and Shielded). We can also see that the state subclasses have a pointer to Player, which is what we’ll use to alter the health and state of the player when necessary. I started by building the abstract State class:

 

State Pattern State HPP

 

This is fairly simple stuff. As the State class is an abstract class it has no implementation. Although note how there’s a forward declaration of the Player class. The Player includes this State header file, as we’ll see later on, in order to access the common interface shared between states as well as have a pointer to state. However we also need the state subclasses to know the player that is being passed to them to change it’s state/alter it’s health when necessary. The important thing to note here is, in this abstract class, all we’re doing is declaring a pointer to player which the state subclasses will use later on; as we don’t need to use any functions from player we can simply use a forward declaration to let the State class know that the Player exists.

 

This saves us from trying something crazy like include the State and Player and include the Player is State. This is called a circular dependency and will not compile because it would be like Player trying to include State which includes Player which includes State which-… I’m sure you get the point. Next we’ll construct our state subclasses.

 

State Pattern Normal HPP

 

State Pattern Shielded HPP

 

The first thing you might notice about the Normal and Shielded classes is that they are Singletons. In my first attempt at the State pattern I used dynamically allocated states, deleting and creating them on the fly; making them Singletons saves all that messing about with memory. As expected they have inherited the functions from the abstract State class and the only different between them is that Shielded has its health variable (as the normal behaviour would be to decrease the player’s health). The real differences can be seen in the implementation:

 

State Pattern Normal CPP

 

State Pattern Shielded CPP

 

Here we can see that, while the Normal class takes damage by decreasing the player’s health, the shielded class takes away its own health and then switches the state of the player back to normal after its health has been depleted. We can also see the importance of passing a pointer to Player to both Normal and Shielded so that we can access functions from Player. Speaking of which:

 

State Pattern Player HPP

 

This is pretty much what you probably expected from the UML diagram at the top of this post. Simples.

 

State Pattern Player CPP

 

From the implementation of Player we can see that the responsibility of what actually happens when Player takes damage is delegated to its current state. If we didn’t do this then putting in an abstract function to take damage in the State class and overriding that function in its subclasses would be moot. What we can also notice is that, were we to add another state (for example a state where no damage is taken at all), then we wouldn’t need to alter the Player class for this as the behaviour defined in the State base class tells Player what it can and can’t do with its states. There’s also some checking to see whether the player is actually still alive which is probably better done using a Boolean but that’s not the main focus here. Next we’ll see how we can use all of what was just created.

 

State Pattern Main CPP

 

After a Player is instantiated, we set it’s state to normal right away (I’m sure that there is a more elegant way to do this), and have him take some damage just to make sure he’s there. Next we give him a shield and pretty much barrage him to death. But what’s really interesting is the result:

 

State Pattern Result

 

We can see that, after the player is shielded, all damage is redirected onto the shield and, when the shield runs out, the player’s state is automatically set back to normal courtesy of the implementation of the takeDamage() function within the Shielded class. Then the expected happens as the player dies because we haven’t invented robot-body technology yet (though I remain confident that it will be developed within my lifespan).

 

And there we have it! The State design pattern. Cool, huh? Here are the files for download should you want them.

This entry was posted in Tutorials and tagged , , , , . Bookmark the permalink.

8 Responses to [Revised] Design Patterns: The State Pattern in C++

  1. Samuel says:

    Nice writeup – enjoyed thinking about the basic idea of modular state – e.g. stacking different effects, items, etc. Maybe you could give some examples of stacking up states?

    • Malcolm says:

      Thanks! Glad you enjoyed reading it although this post has since been updated which may answered your question. To be truthful I’m unfamiliar with the term of “stacking up states”; could you elaborate please?

  2. Yonatan says:

    is there is any reason that the player private member of class shielded and class normal is not protected member of the pure abstract class State?

    • Malcolm says:

      Actually, no; it would make perfect sense to have a pointer to player as a protected member of the abstract state class and I’d encourage people to do that where possible.

  3. Vlad says:

    Aren’t the states supposed to be initialised with the player malcolm? E.g.: Normal::Instance()->initialise(&malcolm)

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>