Strategy

Summary:  Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
Frequency of use:
Medium high

UML class diagram

Participants

The classes and objects participating in this pattern are:

  • Strategy  (SortStrategy)
    • declares an interface common to all supported algorithms. Context uses this interface to call the algorithm defined by a ConcreteStrategy
  • ConcreteStrategy  (QuickSort, ShellSort, MergeSort)
    • implements the algorithm using the Strategy interface
  • Context  (SortedList)
    • is configured with a ConcreteStrategy object
    • maintains a reference to a Strategy object
    • may define an interface that lets Strategy access its data.

Structural code in C#

This structural code demonstrates the Strategy pattern which encapsulates functionality in the form of an object. This allows clients to dynamically change algorithmic strategies.

     

using System;

 

namespace DoFactory.GangOfFour.Strategy.Structural

{

  /// <summary>

  /// MainApp startup class for Structural

  /// Strategy Design Pattern.

  /// </summary>

  class MainApp

  {

    /// <summary>

    /// Entry point into console application.

    /// </summary>

    static void Main()

    {

      Context context;

 

      // Three contexts following different strategies

      context = new Context(new ConcreteStrategyA());

      context.ContextInterface();

 

      context = new Context(new ConcreteStrategyB());

      context.ContextInterface();

 

      context = new Context(new ConcreteStrategyC());

      context.ContextInterface();

 

      // Wait for user

      Console.ReadKey();

    }

  }

 

  /// <summary>

  /// The 'Strategy' abstract class

  /// </summary>

  abstract class Strategy

  {

    public abstract void AlgorithmInterface();

  }

 

  /// <summary>

  /// A 'ConcreteStrategy' class

  /// </summary>

  class ConcreteStrategyA : Strategy

  {

    public override void AlgorithmInterface()

    {

      Console.WriteLine(

        "Called ConcreteStrategyA.AlgorithmInterface()");

    }

  }

 

  /// <summary>

  /// A 'ConcreteStrategy' class

  /// </summary>

  class ConcreteStrategyB : Strategy

  {

    public override void AlgorithmInterface()

    {

      Console.WriteLine(

        "Called ConcreteStrategyB.AlgorithmInterface()");

    }

  }

 

  /// <summary>

  /// A 'ConcreteStrategy' class

  /// </summary>

  class ConcreteStrategyC : Strategy

  {

    public override void AlgorithmInterface()

    {

      Console.WriteLine(

        "Called ConcreteStrategyC.AlgorithmInterface()");

    }

  }

 

  /// <summary>

  /// The 'Context' class

  /// </summary>

  class Context

  {

    private Strategy _strategy;

 

    // Constructor

    public Context(Strategy strategy)

    {

      this._strategy = strategy;

    }

 

    public void ContextInterface()

    {

      _strategy.AlgorithmInterface();

    }

  }

}

Output
Called ConcreteStrategyA.AlgorithmInterface()
Called ConcreteStrategyB.AlgorithmInterface()
Called ConcreteStrategyC.AlgorithmInterface()

Real-world code in C#

This real-world code demonstrates the Strategy pattern which encapsulates sorting algorithms in the form of sorting objects. This allows clients to dynamically change sorting strategies including Quicksort, Shellsort, and Mergesort.

    

using System;

using System.Collections.Generic;

 

namespace DoFactory.GangOfFour.Strategy.RealWorld

{

  /// <summary>

  /// MainApp startup class for Real-World

  /// Strategy Design Pattern.

  /// </summary>

  class MainApp

  {

    /// <summary>

    /// Entry point into console application.

    /// </summary>

    static void Main()

    {

      // Two contexts following different strategies

      SortedList studentRecords = new SortedList();

 

      studentRecords.Add("Samual");

      studentRecords.Add("Jimmy");

      studentRecords.Add("Sandra");

      studentRecords.Add("Vivek");

      studentRecords.Add("Anna");

 

      studentRecords.SetSortStrategy(new QuickSort());

      studentRecords.Sort();

 

      studentRecords.SetSortStrategy(new ShellSort());

      studentRecords.Sort();

 

      studentRecords.SetSortStrategy(new MergeSort());

      studentRecords.Sort();

 

      // Wait for user

      Console.ReadKey();

    }

  }

 

  /// <summary>

  /// The 'Strategy' abstract class

  /// </summary>

  abstract class SortStrategy

  {

    public abstract void Sort(List<string> list);

  }

 

  /// <summary>

  /// A 'ConcreteStrategy' class

  /// </summary>

  class QuickSort : SortStrategy

  {

    public override void Sort(List<string> list)

    {

      list.Sort(); // Default is Quicksort

      Console.WriteLine("QuickSorted list ");

    }

  }

 

  /// <summary>

  /// A 'ConcreteStrategy' class

  /// </summary>

  class ShellSort : SortStrategy

  {

    public override void Sort(List<string> list)

    {

      //list.ShellSort(); not-implemented

      Console.WriteLine("ShellSorted list ");

    }

  }

 

  /// <summary>

  /// A 'ConcreteStrategy' class

  /// </summary>

  class MergeSort : SortStrategy

  {

    public override void Sort(List<string> list)

    {

      //list.MergeSort(); not-implemented

      Console.WriteLine("MergeSorted list ");

    }

  }

 

  /// <summary>

  /// The 'Context' class

  /// </summary>

  class SortedList

  {

    private List<string> _list = new List<string>();

    private SortStrategy _sortstrategy;

 

    public void SetSortStrategy(SortStrategy sortstrategy)

    {

      this._sortstrategy = sortstrategy;

    }

 

    public void Add(string name)

    {

      _list.Add(name);

    }

 

    public void Sort()

    {

      _sortstrategy.Sort(_list);

 

      // Iterate over list and display results

      foreach (string name in _list)

      {

        Console.WriteLine(" " + name);

      }

      Console.WriteLine();

    }

  }

}

Output
QuickSorted list
 Anna
 Jimmy
 Samual
 Sandra
 Vivek

ShellSorted list
 Anna
 Jimmy
 Samual
 Sandra
 Vivek

MergeSorted list
 Anna
 Jimmy
 Samual
 Sandra
 Vivek

.NET Optimized code in C#


The .NET optimized code demonstrates the same real-world situation as above but uses modern, built-in .NET features, such as, generics, reflection, LINQ, lambda functions, and more. You can find an example on our Singleton pattern page.

All other patterns, and so much more, are available in our Dofactory .NET product.


Dofactory .NET includes the Gang of Four and Enterprise patterns, but also many other innovations including our Ultra-Clean™ Architecture, powerful low-code tactics, Rapid Application Development (RAD) techniques, and much more.

Accelerate your application development to where you can write entire solutions in just 33 days!. This unique package will change your outlook on development and your career.  Here's what is included:






Dofactory .NET
.NET Developer Pack




Learn More



  • 69 gang-of-four pattern projects
  • 46 head-first pattern projects
  • Fowler's enterprise patterns
  • Multi-tier patterns
  • Convention over configuration
  • Active Record and CQRS patterns
  • Repository and Unit-of-Work patterns
  • MVC, MVP, & MVVM patterns
  • SparkTM Rapid App Dev (RAD) data access
  • Complete Analytics, Dashboard App
  • Complete Art Shop, Ecommerce App
  • Complete SaaS, Multi-Tenant App
  • Complete CRM, Customer Relationship App
  • 33-Day App Factory™
  • Everything 100% source code




Stay Inspired!
Join other developers and designers who have already signed up for our mailing list.
Terms     Privacy     Licensing       EULA       Sitemap      
© Data & Object Factory, LLC.
Made with    in Austin, Texas