Joydip Kanjilal
Contributor

How to use the strategy design pattern in .Net

how-to
Apr 15, 20194 mins
C#Microsoft .NETSoftware Development

Take advantage of the strategy design pattern to encapsulate a set of algorithms inside a class and apply them based on input

head scratcher strategy thinking
Credit: Thinkstock

Design patterns are used to solve common design problems in software development and to reduce the complexities in our source code. Design patterns can be creational (related to object creation), structural (related to object assembly), or behavioral (related to object collaboration and separation of responsibilities).

The strategy design pattern is a Gang-of-Four (GoF) design pattern. It is a behavioral pattern used to define a family of algorithms and encapsulate each of them inside a class. These encapsulated algorithms are then interchangeable — i.e., they can vary based on different inputs, independently of the client that uses them.

In other words, the strategy design pattern decomposes implementation code into concrete classes and hence promotes reusability. This article presents a discussion of the strategy design pattern and how it can be implemented in C#.

Strategy design pattern participants

The participants in a typical implementation of the strategy design pattern include the following:

  • Strategy — used to declare a common interface for all concrete strategy types. The Context takes advantage of the Strategy interface to invoke an algorithm at runtime.
  • ConcreteStrategy — used to implement the algorithm that is declared in the Strategy interface.
  • Context — contains a reference to the Strategy instance and uses this reference to invoke the algorithm that is defined by a concrete strategy type.

Implement the Strategy interface in C#

So far so good. Now that we have the concepts, let’s now implement the pattern. Assume that you are to design a strategy for sorting algorithms. As an example, assume that you need to sort an array of integers. There are sorting algorithms aplenty, so you would like to defer the choice of the sorting algorithm to be used. Here is where the strategy design pattern comes into play.

The following abstract class represents the Strategy type. This class contains the declaration of the abstract Sort method.

abstract class SortStrategy
  {
    public abstract void Sort(int[] list);
  }

The concrete strategy classes implement the Sort method and represent a sorting algorithm. In this example, we’ve considered the following sorting algorithms:

  1. Quick sort
  2. Shell sort
  3. Bubble sort
  4. Merge sort
  5. Heap sort

Implement the ConcreteStrategy classes in C#

The concrete strategy classes shown below extend the SortStrategy abstract class and implement the Sort method.

class QuickSort : SortStrategy
    {
        public override void Sort(int[] list)
        {
            Console.WriteLine("Quick Sort");
        }
    }
    class ShellSort : SortStrategy
    {
        public override void Sort(int[] list)
        {
            Console.WriteLine("Shell Sort");
        }
    }
    class BubbleSort : SortStrategy
    {
        public override void Sort(int[] list)
        {
            Console.WriteLine("Bubble Sort");
        }
    }
    class MergeSort : SortStrategy
    {
        public override void Sort(int[] list)
        {
            Console.WriteLine("Merge Sort");
        }
    }
    class HeapSort : SortStrategy
    {
        public override void Sort(int[] list)
        {
            Console.WriteLine("Heap Sort");
        }
    }

Note that I’m leaving it to you to implement the sorting algorithms in the Sort method of each of these concrete strategy classes.

Implement the Context class in C#

The Context class contains a reference to SortStrategy. It also contains two methods — the SetSortStrategy method and a Sort method. While the former is used to set the sort strategy to be used, the latter is used to invoke the Sort method based on the sort strategy chosen.

class Context
    {
        private const int MAX = 10;
        private int[] numbers = new int[MAX];
        private SortStrategy _sortstrategy;
        public void SetSortStrategy(SortStrategy sortstrategy)
        {
            _sortstrategy = sortstrategy;
        }
        public void Sort()
        {
            _sortstrategy.Sort(numbers);
        }
    }

And the code snippet below shows how you can create an instance of the Context class, pass a sort strategy, and call the Sort method.

static void Main(string[] args)
        {
            Context context = new Context();
            context.SetSortStrategy(new QuickSort());
            context.Sort();
            Console.Read();
        }

The complete source code is given below for your reference.

using System;
namespace StrategyDesignPattern
{
    abstract class SortStrategy
    {
        public abstract void Sort(int[] list);
    }
    class QuickSort : SortStrategy
    {
        public override void Sort(int[] list)
        {
            Console.WriteLine("Quick Sort");
        }
    }
    class ShellSort : SortStrategy
    {
        public override void Sort(int[] list)
        {
            Console.WriteLine("Shell Sort");
        }
    }
    class BubbleSort : SortStrategy
    {
        public override void Sort(int[] list)
        {
            Console.WriteLine("Bubble Sort");
        }
    }
    class MergeSort : SortStrategy
    {
        public override void Sort(int[] list)
        {
            Console.WriteLine("Merge Sort");
        }
    }
    class HeapSort : SortStrategy
    {
        public override void Sort(int[] list)
        {
            Console.WriteLine("Heap Sort");
        }
    }
    class Context
    {
        private const int MAX = 10;
        private int[] numbers = new int[MAX];
        private SortStrategy _sortstrategy;
        public void SetSortStrategy(SortStrategy sortstrategy)
        {
            _sortstrategy = sortstrategy;
        }
        public void Sort()
        {
            _sortstrategy.Sort(numbers);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Context context = new Context();
            context.SetSortStrategy(new QuickSort());
            context.Sort();
            Console.Read();
        }
    }
}

When you run this program, the following text message will be displayed in the console window:

Quick Sort

As the name implies, the strategy design pattern is a strategy of dealing with multiple ways to solve a problem. The strategy design pattern can be used to encapsulate different behaviors of an object and use them in different circumstances. Some typical use cases of the strategy design pattern include implementing sorting algorithms, implementing different file compression algorithms, implementing various types of serialization, etc. 

Joydip Kanjilal
Contributor

Joydip Kanjilal is a Microsoft Most Valuable Professional (MVP) in ASP.NET, as well as a speaker and the author of several books and articles. He received the prestigious MVP award for 2007, 2008, 2009, 2010, 2011, and 2012.

He has more than 20 years of experience in IT, with more than 16 years in Microsoft .Net and related technologies. He has been selected as MSDN Featured Developer of the Fortnight (MSDN) and as Community Credit Winner several times.

He is the author of eight books and more than 500 articles. Many of his articles have been featured at Microsoft’s Official Site on ASP.Net.

He was a speaker at the Spark IT 2010 event and at the Dr. Dobb’s Conference 2014 in Bangalore. He has also worked as a judge for the Jolt Awards at Dr. Dobb's Journal. He is a regular speaker at the SSWUG Virtual Conference, which is held twice each year.

More from this author