The strategy pattern

The strategy pattern basically allows an algorithm to be selected dynamically at runtime without modifying the client code.

For example, if we have lot of input data from past weather information and we need to forecast the weather, we could perhaps infer based on purely statistical values from the past or from an algorithm doing some kind of scientific manipulation or both. After doing the calculations, we would want to compare the results to check the effectiveness, for example. In this scenario, instead of changing the client code each time, we just supply a different algorithm implementation to the client, thus incurring maybe just a single line of code change. So, the strategy pattern lets the algorithm vary independently from clients using it.

The simple UML diagram for the strategy pattern looks like the following:

Let's talk about the example code. We want to travel between two points, A and B, on the map and need to calculate the duration. We encapsulate the duration calculation algorithm in the strategy so that we can calculate the duration while traveling in the car and traveling via public transport. Therefore, our class diagram will look like the following for our example code:

Jumping on to the code, let's look at the code of the context class, that is, TravelDurationCalculator:

    public class TravelDurationCalculator 
{
private IDurationCalculator strategy;

public TimeSpan Measure(string pointA, string pointB)
{
return strategy.Measure(pointA, pointB);
}

//Change the strategy
public void SetCalculator(IDurationCalculator strategy)
{
this.strategy = strategy;
}
}

From this class, you know how the flow is controlled, so let's see the interface for our strategy:

    public interface IDurationCalculator 
{
TimeSpan Measure(string pointA, string pointB);
}

Now let's see the simple code for our classes implementing the strategies:

    /// <summary> 
/// Travel duration calculating strategy using car
/// </summary>
public class CarDurationCalculator : IDurationCalculator
{
public TimeSpan Measure(string pointA, string pointB)
{
//Calculate and return the time duration value..
return new TimeSpan(4, 46, 0);
}
}
/// <summary>
/// Travel duration calculating strategy using public
transport (bus, tram, train..)
/// </summary>
public class PublicTransportDurationCalculator :
IDurationCalculator
{
public TimeSpan Measure(string pointA, string pointB)
{
//Calculate and return the time duration value..
return new TimeSpan(6, 02, 0);
}
}

After seeing this ultimate algorithm for the travel duration calculator, let's look at what the client code would look like the following:

    public void Test_Strategy_Pattern() 
{
string pointA = "Berlin";
string pointB = "Frankfurt";
TimeSpan timeSpan;
var durationCalculator = new TravelDurationCalculator();

durationCalculator.SetCalculator(new
PublicTransportDurationCalculator());
timeSpan = durationCalculator.Measure(pointA, pointB);
Trace.WriteLine(pointA + " to " + pointB + " takes " +
timeSpan.ToString() + " using public transport.");

durationCalculator.SetCalculator(new CarDurationCalculator());
timeSpan = durationCalculator.Measure(pointA, pointB);
Trace.WriteLine(pointA + " to " + pointB + " takes " +
timeSpan.ToString() + " using car.");
}

The output of this client test code is as follows:

Berlin to Frankfurt takes 06:02:00 using public transport.
Berlin to Frankfurt takes 04:46:00 using car.

I hope this wonderful design pattern is well understood now.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.14.131.212