Practical Introduction to Strategy Design Pattern Using Java
What is Strategy Design Pattern?
Strategy design pattern is a behavioural design pattern. It is a tried and tested way of code design that can be used in scenarios where we need to pick up a specific approach (algorithm) from a pool of available related approaches during runtime to achieve something.
This design pattern is also sometimes referred to as the policy pattern.
In this article, let’s look at a practical scenario to utilize this design pattern and let’s write some code in Java to get a hands-on exposure.
Let’s assume that we have our fictional application that contains some awesome articles and their corresponding URLs (think of Hackernews, maybe?).
you have built this app for the sole purpose of sharing cool articles. now, a rather fascinating idea dawns upon you while you are in the loo. What if you had a feature where your users could share these article links with their connections on various social media? after all, every application and its mother have this feature these days.
After reading through a couple of API documents of different social media apps, you quickly understand that not all social media share API are created equally. sigh :(
so now we are at the point where we have a variety of methods to share the content and we have to choose one depending on the social media app selected by the user (at runtime, in essence). Somehow this sounds familiar to you because this a textbook situation to use a strategy pattern, by definition.
The first step in architecting code following a strategy design pattern is to declare the policy or the strategy (algorithm family). In our case, it would be the steps we would need to share links.
What better way to create a contract or a policy than to use an interface? so, we jump on the keyboard and design the SocialActions interface as follows:
The Interface / Policy:
Now that we have the family defined (which is “Share”), we need to create a pool of algorithms.
In our case, the sharing algorithm varies depending on the platform on which it is to be shared. So we abstract out the implementation of the sharing algorithm for each platform into its own corresponding adapter classes. By this way, our application at any time has to deal with only a single share method with a pre-defined signature.
For the sake of simplicity and to stay on the point of demonstrating the design pattern, let’s just do only console logs in these variants of the share algorithms instead of actually implementing the sharing mechanisms.
The Context Class:
Now we have four different sharing algorithms to choose from and it is time we created a way to simplify the selection process at runtime for our app by creating a layer of abstraction and expose a consistent and predictable method to share URLs.
This not only makes our code cleaner but also makes the maintenance process less of a nightmare.
Finally, let’s look at an example usage of the code we have crafted so far:
The output of the sample driver code above will be as follows:
Thus we have designed a system that will pick the appropriate sharing mechanism at runtime from a pool of available sharing algorithms using the strategy design pattern.
The advantages of this design are that we could extend the system without modifying it (remember Open-Close in S.O.L.I.D principle?). What do we mean by that? you ask. Let’s say a month after pushing this feature to production, you find out that a large portion of your users use Instagram and would like to have that as an option too. At this point, all you have to do is create an adapter for Instagram and be done with it. Easy extension, happy maintenance :)
Advantage number 2, your adapters are isolated and can be tested with ease. Also separating these implementation details makes mocking a walk in the park while unit testing.
Advantage number 3, in this design, if you look at closely, we have intentionally reduced inheritance as much as we can. A spec change tomorrow could be easily dealt with composition technique.
Hope you found this useful and thanks for reading through my thoughts.