The state pattern

The state pattern allows the change in the object's behavior based on the change of its state.

If the state is changing for an object, the behavior automatically changes as well. For example, a person whose state is nervous behaves strangely, while a person whose state is happy behaves in a more positive way.

The state pattern basically implements the state machine in a way that each state is a derived class of a state interface, and they alter between them jumping from one state to another, thus dynamically updating the behavior as per the state.

Let's jump to our example. We want to know the number of days in a season, either summer, winter, autumn, or spring. We will always invoke one single method to know the number of days while we want the object to shift its state automatically to the next season and therefore change its behavior and give us the different number of days on the next call to the same method.

The UML class diagram for the state pattern applied to our example looks like the following:

Now it's time to make things more clear, so let's talk code. First of all, I will show you the client code so that we can see the big picture directly, which I might have failed to explain very clearly:

    public void Test_State_Pattern() 
{
var weatherTeller = new WeatherTeller();

var weatherDays = weatherTeller.GetWeatherDays();
Trace.WriteLine(string.Format("Name: {0} - Days: {1}",
weatherDays.Weather, weatherDays.Days));

weatherDays = weatherTeller.GetWeatherDays();
Trace.WriteLine(string.Format("Name: {0} - Days: {1}",
weatherDays.Weather, weatherDays.Days));

weatherDays = weatherTeller.GetWeatherDays();
Trace.WriteLine(string.Format("Name: {0} - Days: {1}",
weatherDays.Weather, weatherDays.Days));

weatherDays = weatherTeller.GetWeatherDays();
Trace.WriteLine(string.Format("Name: {0} - Days: {1}",
weatherDays.Weather, weatherDays.Days));

weatherDays = weatherTeller.GetWeatherDays();
Trace.WriteLine(string.Format("Name: {0} - Days: {1}",
weatherDays.Weather, weatherDays.Days));
}

Let's look at the interface for the context and the class implementing the WeatherTeller context:

    internal interface IStateContext 
{
void SetState(IWeatherDaysTellerForState newWeatherState);
}

This is the interface for the implanting class:

    public class WeatherTeller : IStateContext 
{
private IWeatherDaysTellerForState weatherDaysTellerState;

public WeatherTeller()
{
weatherDaysTellerState = new SummerDaysTeller();
}

public WeatherDays GetWeatherDays()
{
return weatherDaysTellerState.GetWeatherDays(this); ;
}

/// <summary>
/// Internal interface IStateContext implementation
/// </summary>
void IStateContext.SetState(IWeatherDaysTellerForState
newWeatherState)
{
weatherDaysTellerState = newWeatherState;
}
}

The interface for the state classes:

    internal interface IWeatherDaysTellerForState 
{
WeatherDays GetWeatherDays(IStateContext stateContext);
}

Finally, here is the code for one of the state classes:

    internal class SummerDaysTeller : IWeatherDaysTellerForState 
{
public WeatherDays GetWeatherDays(IStateContext stateContext)
{
stateContext.SetState(new AutumnDaysTeller());

return new WeatherDays()
{
Weather = "Summer",
Days = 150 //5 months * 30
};
}
}

This completes our state pattern. In fact, this is the last design pattern we cover in this chapter.

I imagine you have understood this pattern as well as the others. Download the complete source code and run through the code to get the complete essence.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.235.23