Page 1 of 1

Design Patterns - State Analysis of State Machine Pattern

#1 MentalFloss  Icon User is offline

  • "ADDICTED"[2:5]
  • member icon

Reputation: 526
  • View blog
  • Posts: 1,397
  • Joined: 02-September 09

Posted 11 August 2010 - 10:33 PM

*
POPULAR

Hello again.

I was browsing through some posts of my past and came across a description of the state machine pattern. Since it was requested to have tutorials on design patterns, I figured I'll whip this up for you guys by using my example from my old post.

First, here's a great resource on it (State Pattern). If that's enough for you, cool. Otherwise, let's make a traffic light!

The state pattern allows an object's context to change at any given moment which actually alters its behavior. I think a traffic light is great because we know what the order of states are and it's also repeating.

Green to yellow. Yellow to red. Red to green. Simple!

In this example, our context is the traffic light. If you think about it, we always have the same traffic light but the light it's currently on is always changing. So, here's a light:

namespace StateMachineDemo
{
    /// <summary>
    /// Represents the thing that changes state throughout its life.
    /// </summary>
    public class TrafficLight
    {
        // We'll get to coding this a bit later...
    }
}



We need our state now. Remember that concrete states implement the state so this is an interface. Let's require two things for the contract: a way to change it and a way to report it.

namespace StateMachineDemo
{
    /// <summary>
    /// Contract specification for all states in use.
    /// </summary>
    public interface ITrafficLightState
    {
        // It takes the existing light and changes it.
        void Change(TrafficLight light);

        // We'll display the color it's on.
        void ReportState();
    }
}



Next, we'll create our concrete states. I'm going with GreenLight, YellowLight, and RedLight.

namespace StateMachineDemo
{
    public class GreenLight : ITrafficLightState
    {
        public void Change(TrafficLight light)
        {
            // We'll fill this in a bit later...
        }

        public void ReportState()
        {
            Console.WriteLine("Green Light");
        }
    }

    public class YellowLight : ITrafficLightState
    {
        public void Change(TrafficLight light)
        {
            // We'll fill this in a bit later...
        }

        public void ReportState()
        {
            Console.WriteLine("Yellow Light");
        }
    }

    public class RedLight : ITrafficLightState
    {
        public void Change(TrafficLight light)
        {
            // We'll fill this in a bit later...
        }

        public void ReportState()
        {
            Console.WriteLine("Red Light");
        }
    }
}



Let's work on the context a little now.

We need it to hold a state:

namespace StateMachineDemo
{
    /// <summary>
    /// Represents the thing that changes state throughout its life.
    /// </summary>
    public class TrafficLight
    {
        public ITrafficLightState State { get; set; }
    }
}



It has to be open like that because we're going to need outside code to change the context.

Now, to make it pretty, we'll have the same method Change on it but without passing anything. So, when we want the traffic light to change, it will but we will not know the internals of that change! We do the same for reporting state even though that took no parameters to begin with...

namespace StateMachineDemo
{
    /// <summary>
    /// Represents the thing that changes state throughout its life.
    /// </summary>
    public class TrafficLight
    {
        public ITrafficLightState State { get; set; }

        public void Change()
        {
            State.Change(this);
        }

        public void ReportState()
        {
            State.ReportState();
        }
    }
}



Now we hook everything together into a main test method:

namespace StateMachineDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            TrafficLight light = new TrafficLight();

            // Normally we would want a constructor doing this but I did it
            // that way in other post so this is just another way.
            light.State = new RedLight();

            // Now we just change it a bunch and report:
            for (int count = 0; count < 9; count++)
            {
                light.Change();
                light.ReportState();
            }

            Console.ReadLine();
        }
    }
}



OH NO! What have we forgotten? We run it and get this:

Quote

Red Light
Red Light
Red Light
Red Light
Red Light
Red Light
Red Light
Red Light
Red Light


Well, we have to actually change the states... so let's go back to that code that has concrete states and make the specification fit:

Quote

Red to Green. Green to Yellow. Yellow to Red.


namespace StateMachineDemo
{
    public class GreenLight : ITrafficLightState
    {
        public void Change(TrafficLight light)
        {
            light.State = new YellowLight();
        }

        public void ReportState()
        {
            Console.WriteLine("Green Light");
        }
    }

    public class YellowLight : ITrafficLightState
    {
        public void Change(TrafficLight light)
        {
            light.State = new RedLight();
        }

        public void ReportState()
        {
            Console.WriteLine("Yellow Light");
        }
    }

    public class RedLight : ITrafficLightState
    {
        public void Change(TrafficLight light)
        {
            light.State = new GreenLight();
        }

        public void ReportState()
        {
            Console.WriteLine("Red Light");
        }
    }
}



Whew! All is right with the world:

Quote

Green Light
Yellow Light
Red Light
Green Light
Yellow Light
Red Light
Green Light
Yellow Light
Red Light


Hope this helps. Have fun.

Is This A Good Question/Topic? 8
  • +

Replies To: Design Patterns - State

#2 Sergio Tapia  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1252
  • View blog
  • Posts: 4,168
  • Joined: 27-January 10

Posted 12 August 2010 - 06:30 AM

Great stuff, design patterns are something every developer should be aware of to create better software. Thanks for taking the time to write these easy to understand examples.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1