[C# Design Patterns] The Strategy Pattern

This post will demonstrate the strategy design pattern.

 

What it is

The Strategy Design Pattern can be used when you want to perform a function, but you might use different techniques.

For a non-computer example, let’s say I want some food to eat. There are several ways I can accomplish that: cook a meal in my kitchen, go to a restaurant, order food to be delivered to me, etc.

All those strategies perform the “function” I want – “get food”. But they do them differently.

 

Video version of demonstration

 

Examples

For this example, I’ll show a calculator class that needs to calculate the average of a list of numbers, using either the “mean” or “median” technique of averaging. The “strategy” is the different way to compute the average.

 

Non-Pattern Versions

 

Non-pattern version (multiple methods)

This version shows how the calculator class could be written using different functions – one for each averaging technique.

 

Non-pattern version (single methods)

This is how the class could be written, using a single function with a “switch” statement.

 

Design Pattern Version

 

Strategy Design Pattern version

The version using the design pattern is a little more complex. It uses four classes/interfaces, while the non-pattern versions only use one class. It wouldn’t be worth the extra work, for code as small as this sample.

I would probably only consider using this pattern if there were at least five different ways to perform the strategy’s function. Or, if I could re-use the concrete strategy classes in several places.

 

IAveragingMethod.cs

This is the interface for the strategy.

The interface states that the “concrete strategy” classes (the classes that perform the function) need to have these properties/methods/etc.

For this example, the concrete strategy classes need an “AverageFor” function, which accepts a list of doubles, and returns a double.

 

AverageByMean.cs

The concrete strategy to calculate an average, using the “mean” method.

 

AverageByMedian.cs

The concrete strategy to calculate an average, using the “median” method.

 

Calculator.cs

The function to calculate the average receives a list of numbers, and an object that is one of the concrete strategy classes. Because the datatype for the averagingMethod parameter is “IAveragingMethod”, we can pass in any object that implements that interface (matches the requirements for our strategy).

Then, the CalculateAverageFor() method uses the AverageFor() function in the concrete strategy class to perform the calculation.

 

TestCalculator.cs

This is how you would call a method that uses the strategy design pattern.

You pass in the list of numbers to average, and an instance of the appropriate concrete strategy class.

 

Where I’ve found it useful

The most common place for me to use this design pattern is when I need to validate a business object, but have several different ways it might need to be validated. This pattern lets me call a single “Validate” function that accepts the business object and the appropriate concrete strategy validator object.

This design pattern, and the Command Design Pattern, are examples of dependency inversion. Dependency inversion is a technique that can make your code easier to modify, and easier to test.

This is also a technique you can use to implement “composition over inheritance” – another pattern I’ll demonstrate soon.

 

All my design pattern lessons

Source code for my design pattern lessons

 

4 thoughts on “[C# Design Patterns] The Strategy Pattern

  1. Hey. Been enjoying your design pattern videos a great deal. Thanks. Small suggestion about the volume, which is pretty low in a few cases. You can increase or decrease an upload’s volume after the fact. See <a href=”https://www.youtube.com/watch?v=dvxTWXVMikg” target=”_blank”>this video</a>.

    On topic of pattern use. I’m working on a text adventure that will be running in WPF. I’m looking for <a href=”http://stackoverflow.com/questions/3845458/coding-interactions-in-a-text-adventure” target=”_blank”>this type</a> interaction behavior, but I’m having a hard time deciphering from that post how to implement this sort of thing. Is there a pattern that might be handy in this situation? I’m currently looking into the Visitor pattern, but I haven’t researched it far enough to know if it’s going to be useful (same with the Strategy pattern). I’d like to avoid code repetition as much as possible and keep things neat — my previous attempt at a text adventure (running in the console), while functional, was a jumbled mess, full of switch statements for every conceivable player input (didn’t use a parser at the time). This was before I came across your RPG tutorial, which, among other things, taught me sensible code structure.

    So far I can match an interaction to the correct response, but I’m reluctant to scale up in fear of going down the wrong path.

    A side note.
    The way I’m matching interactions with responses right now is, every item has a set of states (enum), as do the responses (each response also targets a specific item). If the currentItem’s states and ID match any response, you get the appropriate response. Probably not ideal, but it’s working for the moment.

    <code>
    Items.Add(new Item(ITEM_ID_APT_BEER, “apartment beer”, BeerVerbs, BeerSpelling,
    canReach: State.Accessible,
    canSee: State.Visible,
    canTake: State.Collectable,
    canDrink: State.Drinkable));
    </code>
    (all states are optional; also I didn’t want the parameter order to be an issue, so I’m using parameter names in the constructor)
    (apt is short for apartment; the beer is in the fridge; for testing purposes it is accessible, otherwise it’s inaccessible until the player opens the fridge)

    <code>
    Responses.Add(new Response(APT_BEER_FIRDGE_PICKUP_POS_RESPONSE, “You pick up the beer can. Your fridge is now one beer can short.”, ITEM_ID_APT_BEER,
    canReach: State.Accessible,
    canTake: State.Collectable));

    foreach (State state in States.GetValues<State>())
    {
    Console.WriteLine(state);
    foreach (Response r in Responses)
    if ((r.TargetID == currentItem.ID) && (r.CanDrink == state) && (currentItem.CanDrink == state))
    {
    Console.WriteLine(r.Content);
    break;
    }
    }
    </code>

    1. Can you give me a couple days to think about this?

      My first instinct is to build the state machine (which, I assume, is in the Item base class) so it lets you define the available “action” and “response” combinations it understands. With a function like:
      public void AddActionResponse(Action action, Response response). I think this will be cleaner than adding more parameters to the constructor, as you add more functionality to the game.

      That pair is added to a Dictionary variable inside the state machine. If the player tries to “take the house”, the state machine would know that is not possible – because there is no “Take” action in its dictionary. Or, you could initialize it so the response to a “Take” action, for a house object, is to display a message “You aren’t that strong!”

      But, I’d like to think a bit more about this, to consider if there are problems with this solution, or if there is a better way to do this.

Leave a Reply

Your email address will not be published. Required fields are marked *