Design Pattern articles in this series are listed below:

Design Patterns - An Overview
Design Patterns – Using the Strategy Pattern in C#
Design Patterns – Using the Singleton Pattern in C#
Design Patterns – Using the Adapter Pattern in C#
Design Patterns - Using the Facade Pattern in C#
Design Patterns - Using the Composite Pattern in C#
Design Patterns - Using the Decorator Pattern in C#
Design Patterns - Using the Abstract Factory Pattern in C#
Design Patterns – Using the Builder Pattern in C#
Design Patterns - Using the Observer Pattern in C# (Events and Delegates)
Design Patterns – Using the Chain of Responsibility Pattern in C#
Design Patterns – Using the State Pattern in C#
Design Patterns – Which to use When? Take the Quiz!

    What is a Strategy Pattern?
    A Strategy Pattern belongs to the Behavioral Pattern category. It helps in de-coupling the client and the algorithms into separate classes. The object and it’s behavior are encapsulated into their own classes. This pattern helps in several ways. It helps you to switch algorithms at any time. In future, if you decide to add a new algorithm, it’s simpler as all you have to do is add a new class that encapsulates the new behavior.
    When should you use the Strategy pattern? Any logic that has a switch case statement or if conditions are the perfect candidates for implementing the Strategy pattern.
    How is it implemented?
    Let’s take a look at implementing a simple application that serializes data into different formats (such as XML, JSON). We will first look at a code sample that does not use the Strategy Pattern. We will later rewrite to use the Strategy Pattern to understand the benefits.
    It’s pretty common experience for any developer to be faced with situations which require him/her to execute an algorithm based on a variable. In the snippet below, based on the serializeFormat variable, we add logic for serialization.
    class Program
    {
        static void Main(string[] args)
        {
            string serializeFormat = "XML";
    
            switch (serializeFormat)
            {
                case "XML":
                    //Logic to serialize a data source to XML
                    Console.WriteLine("Serializing to XML");
                    break;
                case "JSON":
                    //Logic to serialize a data source to JSON
                    Console.WriteLine("Serializing to JSON");
                    break;
                default:
                    break;
            }
        }
    }
    Let’s rewrite this code using the Strategy Pattern. Let’s take a look at the code first.
namespace StrategyPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            SerializeContext context = new SerializeContext(new XmlSerializerStrategy());

            context.Serialize();
        }
    }
}
    The “Client” implementation
namespace StrategyPattern
{
  public interface ISerializeStrategy
  {
    void Serialize();
  }

  public class XmlSerializerStrategy : ISerializeStrategy
  {
    public void Serialize()
    {
      //Logic to serialize to Xml
      Console.WriteLine("Serializing to Xml");
    }
  }

  public class JsonSerializerStrategy : ISerializeStrategy
  {
    public void Serialize()
    {
      //Logic to serialize to Xml
      Console.WriteLine("Serializing to Json");
    }
  }

  public class SerializeContext
  {
    private ISerializeStrategy serialize;

    public SerializeContext(ISerializeStrategy serialize)
    {
      this.serialize = serialize;
    }

    public void Serialize()
    {
      this.serialize.Serialize();
    }
  }
}
    Implementation of Strategies, Context and the Interface
    The Strategy Pattern consists of 3 distinct components:
    1. A client (In our example, the console application’s Program.cs class)
    2. An Interface that all strategies implement. In our example, the ISerializeStrategy interface.
    3. Different algorithm classes (or Concrete Strategies) that implement the interface. In our example, the classes XmlSerializerStrategy and JsonSerializerStrategy
    4. A Context class. The Context object receives requests from the client and delegates them to the appropriate Concrete Strategies. Note that the client only interacts with the context class. The client does not instantiate the concrete class objects directly. Technically, the Context class contains a reference to the Concrete Strategies. In our example, this is done by declaring a private member of type ISerializeStrategy
    Here’s the class diagram for the above implementation.

image

    As the application grows, you may need to support other types of Serialization as well (say Binary Serializer). All you need to do is create a new BinarySerializerStrategy class that implements the ISerializeStrategy interface and add implementation to the Serialize() method.
    It’s important to note that the Strategy Pattern is a classic example of Aggregation at work. Aggregation is a OOP concept of having a “has a” relationship between the aggregate and the component(as opposed to Inheritence that has a “is a” relationship)
    Conclusion
    This post provides an explanation on how to get started using the Strategy Pattern in C#. Do not forget to subscribe to the RSS feed.

Retweetkick it on DotNetKicks.com