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.
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.
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.
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
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
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.