Exploring the Strategy Pattern

19. August 2015 16:09

 

According to Wikipedia the strategy pattern “is a software design pattern that enables an algorithm’s behavior to be selected at runtime.” Hmm, what the heck does that mean?

 

Let’s explore how this is implemented in the .Net Framework’s Generic List class’s Sort method. For the examples let’s use a List<Vehicle> where the Vehicle class is defined as such:

 

   1: private class Vehicle : IComparable<Vehicle> 
   2: { 
   3:     public int NumberOfWheels { get; set; }
   4:  
   5:     public string Style { get; set; }
   6:  
   7:  
   8:     public override string ToString() 
   9:     { 
  10:         return string.Format("{0}, Wheel Count = {1}", this.Style, this.NumberOfWheels); 
  11:     }
  12:  
  13:     public int CompareTo(Vehicle other) 
  14:     { 
  15:         return this.Style.CompareTo(other.Style); 
  16:     } 
  17: } 
  18:  

 

This is the collection of vehicles we’ll use:

 

   1:  
   2: private IList<Vehicle> _vehicleList = new List<Vehicle> 
   3: { 
   4:  
   5:  new Vehicle() {NumberOfWheels = 2, Style= "Motorcycle"}, 
   6:  
   7:  new Vehicle() {NumberOfWheels = 4, Style= "Sedan"}, 
   8:  
   9:  new Vehicle() {NumberOfWheels = 4, Style= "Truck"}, 
  10:  
  11:  new Vehicle() {NumberOfWheels = 3, Style= "Trike"}, 
  12:  
  13: };

 

So, calling Sort with no parameters does a default sort. In this case using the Vehicle class’s IComparable interface.

 

   1: public void SortTest()
   2: {
   3:     List<Vehicle> testList = new List<Vehicle>(_vehicleList);
   4:     testList.Sort();
   5:     foreach(var item in testList)
   6:     {
   7:         Console.WriteLine(item.ToString());
   8:     }
   9: }

 

As you expect, this sorts the list by the Style property:

 

Motorcycle, Wheel Count = 2
Sedan, Wheel Count = 4
Trike, Wheel Count = 3
Truck, Wheel Count = 4

 

Wait, where is the strategy pattern? It comes into play with the Sort method’s overloads. Let’s say we want to sort the list by the NumberOfWheels property instead. We’ll start by creating a comparer:

 

   1: private class VehicleWheelCountComparer : IComparer<Vehicle>
   2: {
   3:     public int Compare(Vehicle x, Vehicle y)
   4:     {
   5:         if (x.NumberOfWheels.Equals(y.NumberOfWheels))
   6:         {
   7:             return x.Style.CompareTo(y.Style);
   8:         }
   9:         else { return x.NumberOfWheels.CompareTo(y.NumberOfWheels); }
  10:     }
  11: }

 

Then we can pass a new instance of the comparer to the Sort method. This allows us to change the Sort method’s behavior at runtime. The Sort method doesn’t need to know anything about the Vehicle class or how to sort instances of it. It can just use the ‘strategy’ passed into it.

 

   1: public void SortTestWheelCount()
   2: {
   3:     List<Vehicle> testList = new List<Vehicle>(_vehicleList);
   4:     testList.Sort(new VehicleWheelCountComparer());
   5:     foreach (var item in testList)
   6:     {
   7:         Console.WriteLine(item.ToString());
   8:     }
   9: }

 

Now our list is sorted by Wheel Count:

 

Motorcycle, Wheel Count = 2
Trike, Wheel Count = 3
Sedan, Wheel Count = 4
Truck, Wheel Count = 4

About the author

I'm a .NET developer, a husband and a father of three beautiful girls.

Month List