BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Design Patterns
.NET 1.1+

State Design Pattern

The state pattern is a design pattern that allows an object to completely change its behaviour depending upon its current internal state. By substituting classes within a defined context, the state object appears to change its type at run-time.

Example State

In this section we will create a simple example of the state design pattern using C#. This example will simulate the media player described earlier in the article. The two buttons on the media player, "Play" and "Audio Source", will be represented by methods in the state base class and its subclasses.

The example media player will have four possible states. The states will be "MP3 Playing", "MP3 Paused", "Radio" and "Standby" and each will be represented by one of four concrete state classes.

The behaviour of the two buttons will vary according to the currently selected state. The actions for each button will be as follows:

StatePlay ButtonAudio Source Button
StandbyNo effect.Switch state to "MP3 Playing".
MP3 PlayingStop music, switch state to "MP3 Paused".Switch state to "Radio".
MP3 PausedStart music, switch state to "MP3 Playing".Switch state to "Radio".
RadioTune next radio station.Switch state to "Standby".

The skeleton code for the audio player is as follows. NB: The Context in this example is provided by the AudioPlayer class.

public class AudioPlayer
{
    private AudioPlayerState _state;

    public AudioPlayer(AudioPlayerState state)
    {
        _state = state;
    }

    public void PressPlay()
    {
        _state.PressPlay(this);
    }

    public void PressAudioSource()
    {
        _state.PressAudioSource(this);
    }

    public AudioPlayerState CurrentState
    {
        get { return _state; }
        set { _state = value; }
    }
}


public abstract class AudioPlayerState
{
    public abstract void PressPlay(AudioPlayer player);

    public abstract void PressAudioSource(AudioPlayer player);
}


public class StandbyState : AudioPlayerState
{
    public StandbyState()
    {
        Console.WriteLine("STANDBY");
    }

    public override void PressPlay(AudioPlayer player)
    {
        Console.WriteLine("Play pressed: No effect");
    }

    public override void PressAudioSource(AudioPlayer player)
    {
        player.CurrentState = new MP3PlayingState();
    }
}


public class MP3PlayingState : AudioPlayerState
{
    public MP3PlayingState()
    {
        Console.WriteLine("MP3 PLAYING");
    }

    public override void PressPlay(AudioPlayer player)
    {
        player.CurrentState = new MP3PausedState();
    }

    public override void PressAudioSource(AudioPlayer player)
    {
        player.CurrentState = new RadioState();
    }
}


public class MP3PausedState : AudioPlayerState
{
    public MP3PausedState()
    {
        Console.WriteLine("MP3 PAUSED");
    }

    public override void PressPlay(AudioPlayer player)
    {
        player.CurrentState = new MP3PlayingState();
    }

    public override void PressAudioSource(AudioPlayer player)
    {
        player.CurrentState = new RadioState();
    }
}


public class RadioState : AudioPlayerState
{
    public RadioState()
    {
        Console.WriteLine("RADIO");
    }

    public override void PressPlay(AudioPlayer player)
    {
        Console.WriteLine("Play pressed: New station selected");
    }

    public override void PressAudioSource(AudioPlayer player)
    {
        player.CurrentState = new StandbyState();
    }
}

Testing the State

To test the state machine for the audio player and to see the elegance of the simple interface it presents, execute the following code within a console application's Main method.

AudioPlayer player = new AudioPlayer(new StandbyState());
player.PressPlay();
player.PressAudioSource();
player.PressPlay();
player.PressPlay();
player.PressAudioSource();
player.PressPlay();
player.PressAudioSource();

/* OUTPUT

STANDBY
Play pressed: No effect
MP3 PLAYING
MP3 PAUSED
MP3 PLAYING
RADIO
Play pressed: New station selected
STANDBY

*/
21 July 2009