How to use the state design pattern in .Net

Take advantage of the state design pattern to allow an object to change its behavior when its internal state changes

How to use the state design pattern in .Net
tracyshaun (CC BY-SA 2.0)

Design patterns are used to solve common design problems and reduce the complexities in our source code. The state design pattern is a behavioral pattern that is used to represent a one to many relationship between objects in such a way that if one of the objects is modified, then all of the dependent objects are also modified.

The Gang of Four defines the state design pattern as follows:

Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.

This article presents a discussion of how we can work with the state design pattern in .Net.

When to use the state design pattern

The state design pattern is typically needed when you have an object in your application that might pass through various phases. As an example, you might have an application that keeps track of the status of notifications that are sent via emails. At any given time, the status of such notifications could be any of five states: processed, delivered, opened, bounced, or undelivered.

The participants in a representation of the state design pattern would typically include the following classes or objects:

  • Context—the actual object to be accessed by the client.
  • State—the interface (or maybe an abstract class) that encapsulates the behavior of the context.
  • Concrete state—a class that represents the state of the context.

This design pattern can be used when you have a one to many relationship between objects and if one of such objects is modified, all the dependent objects would be notified automatically. 

Implementing the state design pattern in C#

As I said earlier, the state design pattern is used to represent the state of an object and then change the behavior of the object when the state is changed. Let me illustrate this design pattern by creating a simple console application in this next section.

Create a console application project in Visual Studio by following the steps given below.

  1. In the Visual Studio IDE, click on File -> New -> Project.
  2. Select “Console App (.Net Framework)” as the template of choice.
  3. Specify a name for your project.
  4. Click OK.

The following code snippet illustrates an abstract class called State. It contains an abstract method called Process that accepts a reference to an instance of the Context class. We’ll talk about the Context class later.

public abstract class State
    {
        public abstract void Process(Context context);
    }

The following two classes, ConcreteStateOne and ConcreteStateTwo, extend the State class and implement the Process method.

public class ConcreteStateOne : State
    {
        public override void Process(Context context)
        {
            context.State = new ConcreteStateTwo();
        }
    }
public class ConcreteStateTwo : State
    {
        public override void Process(Context context)
        {
            context.State = new ConcreteStateOne();
        }
    }

The Context class is shown below. This class holds an instance of concrete state, meaning it defines the current state. The Context class contains an argument constructor that accepts a reference to an instance of the State class as an argument. It also contains a method named Toggle that when called changes the state of the object.

public class Context
    {
        public Context(State state)
        {
            this.State = state;
        }
        public State State { get; set; }
        public void Toggle()
        {
            State.Process(this);
        }
    }

Lastly, here is how you can create an instance of the Context class and then invoke the Toggle method to change the state of the object.

 static void Main(string[] args)
        {
            Context context = new Context(new ConcreteStateOne());
            context.Toggle();
            context.Toggle();
            Console.Read();
        }

Copyright © 2018 IDG Communications, Inc.