🎉 Hooray! After 3 years of work, I've finally released the ebook on design patterns! Check it out »

C#: Strategy

Strategy

Strategy is a behavioral design pattern that turns a set of behaviors into objects and makes them interchangeable inside original context object.

The original object, called context, holds a reference to a strategy object and delegates it executing the behavior. In order to change the way the context performs its work, other objects may replace currently linked strategy object with another one.

Learn more about Strategy

Application of the pattern in C#

Complexity:

Popularity:

Usage examples: The Strategy pattern is very common in C# code. It’s often used in various frameworks to provide users a way to change the behavior of a class without extending it.

Identification: Strategy pattern can be recognized by a method that lets nested object do the actual work, as well as the setter that allows replacing that object with a different one.

Example: Structure of the Pattern

This example illustrates the structure of the Strategy design pattern. It focuses on answering these questions:

  • What classes does it consists of?
  • What roles do these classes play?
  • In what way the elements of the pattern are related?

Program.cs: Structural Example

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RefactoringGuru.DesignPatterns.Strategy.Structural
{
    class Context
    {
        private Strategy _strategy;

        public Context()
        { }

        public Context(Strategy strategy)
        {
            this._strategy = strategy;
        }

        public void setStrategy(Strategy strategy)
        {
            this._strategy = strategy;
        }

        public void doSomeBusinessLogic()
        {
            Console.Write("Context: Sorting data using the strategy (not sure how it'll do it)\n");
            var result = this._strategy.doAlgorithm(new List<string> { "a", "b", "c", "d", "e" });

            string result_str = string.Empty;
            foreach(var element in result as List<string>)
            {
                result_str += element + ",";
            }

            Console.Write(result_str);
        }
    }

    interface Strategy
    {
        object doAlgorithm(object data);
    }

    class ConcreteStrategyA : Strategy
    {
        public object doAlgorithm(object data)
        {
            var list = data as List<string>;
            list.Sort();

            return list;
        }
    }

    class ConcreteStrategyB : Strategy
    {
        public object doAlgorithm(object data)
        {
            var list = data as List<string>;
            list.Sort();
            list.Reverse();

            return list;
        }
    }

    class Client
    {
        public static void ClientCode()
        {
            var context = new Context();

            Console.Write("Client: Strategy is set to normal sorting.\n");
            context.setStrategy(new ConcreteStrategyA());
            context.doSomeBusinessLogic();
            Console.Write("\n");
            Console.Write("Client: Strategy is set to reverse sorting.\n");
            context.setStrategy(new ConcreteStrategyB());
            context.doSomeBusinessLogic();

            Console.Write("\n");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Client.ClientCode();
        }
    }
}

Output.txt: Output

Client: Strategy is set to normal sorting.
Context: Sorting data using the strategy (not sure how it'll do it)
a,b,c,d,e

Client: Strategy is set to reverse sorting.
Context: Sorting data using the strategy (not sure how it'll do it)
e,d,c,b,a