Home > Design Patterns, SOLID > Strategy Pattern

Strategy Pattern

In this post I am going to talk about another very common pattern which we all use in our code but aren’t aware of it. In fact once you start thinking and re factoring your code you will see how close some of these patterns and at times confusing as well.

In this context the confusion is that in my previous post about Template Method Pattern I said that when ever you have “switch case” kind of logic then Template Method is a good candidate to be used, but same goes for Strategy Pattern and why not as both come under the “Behavioral Pattern” category.

But there is clear distinction between the two , Template is more of control of flow where as Strategy is pure about decision making or strategies, and don’t worry this confusion will fade away as you start using them more and more in your projects.

Lets start by looking at the UML class diagram of this pattern and then we will dissect it one by one.

Strategy Pattern UML Class Diagram

Nothing complicated and lets see the three main classes of this pattern.

  • Strategy: A class that defines an interface for an algorithm(method)
  • Concrete Strategy: A class which implements the defined interface in the strategy
  • Context: Defines all the strategy and gets the concrete strategy to execute the algorithm.

Phew !! Looks confusing and odd, I mean the class diagram was trying to make some sense and then these three little statements made us throw design patterns out of the window. May be it’s not that complicated as it sounds.

Lets say you are designing a CachePolicy class which at runtime will get some settings from a configuration file and depending on Policy ( Strategy) it will cache the data to the storage. Hmm may be it is starting to make some sense as the policy is our strategy and will do switch from one type of storage to another.

We are also doing pretty good when it comes to Object Oriented Analysis and Design (OOAD) as we have identify a behaviour ( Strategy ) and some Inheritance and polymorphism ( different types of storage but a common behavior ).

Lets look how we would implement if we don’t apply SOLID Principles and design patterns and the code would something like this.

public class CachePolicyService
    {
        public void Store(CachePolicyStrategy cachePolicyStrategy, string key, object data)
        {
            switch (cachePolicyStrategy)
            {
                case CachePolicyStrategy.FileServer:
                    StoreToFileCache(key, data);
                    break;
                case CachePolicyStrategy.WebCache:
                    StoreToWebCache(key, data);
                    break;
                case CachePolicyStrategy.StateServer:
                    StoreToStateServerCache(key, data);
                    break;
                case CachePolicyStrategy.Database:
                    StoreToDatabaseCache(key, data);
                    break;
            }
        }

        private void StoreToDatabaseCache(string key, object data)
        {
            throw new NotImplementedException();
        }

        private void StoreToStateServerCache(string key, object data)
        {
            throw new NotImplementedException();
        }

        private void StoreToWebCache(string key, object data)
        {
            throw new NotImplementedException();
        }

        private void StoreToFileCache(string key, object data)
        {
            throw new NotImplementedException();
        }
    }

Well the code looks okay and lets re factor the code to apply the design pattern and the SOLID principle. As you can see there is a switch statement and this class responsibility is to make the decision but not necessary implement each of its implementation in its private method. Specially if each policy has different storage then the Policy service class has to have knowledge of all these storage types and how to store as well. So i hope you guys are with me that this methods do not belong to the Cache Policy service class (SRP)

Lets follow the SOLID principles and re factor some of the code. First we need to take care of various type of storage and the switching logic, so task in our hand is that the Cache Policy Service need to have a way to store the data but without going into how the data is stored, second the various medium of storing the data is different but have a same algorithm (method) i.e. a common store method ( which means abstract method and polymorphism). This is virtually the strategy pattern in english and lets see this in a class diagram.

Strategy Pattern VS class digram

Wow !! we did a pretty good job and it looks pretty close to the first UML diagram and now we are beginning to see the bigger picture.Lets see the code one by one to understand what it means to implement like that.First we will start with the enum which has various kind of strategy.

Cache Policy Strategy

namespace StrategyPattern
{
    public enum CachePolicyStrategy
    {
        FileServer,
        WebCache,
        StateServer,
        Database
    }
}

Cache Policy

namespace StrategyPattern
{
    public abstract class CachePolicy
    {
        public abstract void Store(string key, object data);
    }
}

File Cache

namespace StrategyPattern
{
    public class FileCachePolicy : CachePolicy
    {
        public override void Store(string key, object data)
        {
           //Store it in the file system
        }
    }
}

and you get the picture for rest of the Cache Policy class, however lets see the main CachePolicyService class and see how we have refactored the “switch” statement to the Strategy Pattern.

Cache Policy Service

public class CachePolicyService
    {
        private readonly Dictionary<CachePolicyStrategy, CachePolicy> policies =
            new Dictionary<CachePolicyStrategy, CachePolicy>();

        public CachePolicyService()
        {
            DefineCachePolicies();
        }

        private void DefineCachePolicies()
        {
            policies.Add(CachePolicyStrategy.FileServer, new FileCachePolicy());
            policies.Add(CachePolicyStrategy.WebCache, new WebCachePolicy());
            policies.Add(CachePolicyStrategy.StateServer, new StateCachePolicy());
            policies.Add(CachePolicyStrategy.Database, new DatabaseCachePolicy());
        }

        public void Store(CachePolicyStrategy cachepolicyStrategy,string key,object data)
        {
            policies[cachepolicyStrategy].Store(key, data);
        }
    }

And this is where we are doing some cool re factoring thing.First we are creating a dictionary of these policies (strategies) and adding the classes which implements the “Store” (algorithm) method, its this way we are creating an array of these objects and when the “Store” method is called in the Service class we access the object by its indices and execute the store method. ( This is what we define as role of the context in the beginning after all it’s not that complicated) 😉

As you can see the method signature is defined on the abstract class and all the Policy classes adhere to it and I think this is biggest strength of OOP. Moreover we applying SOLID principle to this class as now this class knows how to call the store method of each of these policies but is not involved in the underlying logic of how the data is stored.

This is really a very handy and powerful pattern and you will see it’s avenue for implementation is infinite. It can easily be combined with Template Method Pattern or Factory Pattern. It’s main use could be in business objects and business rules for example in Tax or Insurance calculation where various strategy can be applied to calculate the tax/insurance based on various attributes like Person age, gender, salary etc.

Advertisements
Categories: Design Patterns, SOLID Tags: , ,
  1. Yogesh
    January 28, 2011 at 11:46 am

    Nice start to 2011.

  1. March 15, 2012 at 7:44 pm
  2. June 18, 2013 at 6:48 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: