As you know, Design Patterns are special solutions designed by experts for common problems. They are not a ready-to-use library or a package, conversely, they are general concepts you can follow to solve your problem regardless of the programming language you use.
There are three major categories for these patterns which are Creational, Structural, and Behavioral Design Patterns.
In this post, we will know the differences between three of so close Behavioral Design Patterns which are Strategy, State, and Template.
We will take the same example to just define the differences easily not to decide that this pattern is the perfect fit for this situation.
Let’s imagine a scenario in which a user can choose from different payment gateways to pay for his order or the payment gateway is predefined in the API.
In Strategy, you can define a family of strategies (algorithms) that can be used interchangeably to solve a specific problem.
As you can see, if we want to add a new payment gateway, all we have to do is just add a new strategy implementing this gateway logic which respects the Open-Closed Principle perfectly.
Let’s jump into our example:
From the previous example, we note that the Strategy pattern lets you change the Order (Context) object behavior at the runtime by injecting a specific payment gateway and its behavior will remain unchanged for the rest of the lifespan of the Order (Context) object.
When should you use the Strategy design pattern?
Simply, when you have many variants (strategies) which can be used interchangeably and you want to switch between them just at the runtime (at the Context creation time).
If your Context object has many if...else
statements, this might be an indicator of replacing them with Strategies.
The State pattern is a specialization of the Strategy pattern and is so close to it.
As you can see, the State pattern almost looks like the Strategy pattern. And like the Strategy, if we want to add a new payment gateway, all we have to do is add a new State which also respects the OCP.
Let’s jump into our example:
From the previous example, you may note here you can switch between the payment gateways ( States) dynamically for the rest of the lifespan of the Order (Context) object.
Where should you implement the State transition?
- Client: As we do in the previous example which decreases the coupling, but unfortunately this isn’t the case all the time.
- Context: In this case, the Context will know about all the possible states and how to transition between them which increases the coupling.
- State: Every state can transition between each other which increases the coupling as well between the states.
So what is the difference between Strategy and State design patterns?
- In the Strategy pattern, the Context behavior changes once by injecting a specific strategy and remains unchanged for the rest of its lifespan. Conversely, in the State pattern, the Context behavior can be changed dynamically during the rest of its lifespan by switching between its States.
- In the State pattern, if the state transition occurs inside each state then every state will know about each other, contrary to the Strategy pattern, strategies don’t know anything about each other.
When should you use the State design pattern?
Simply, when your object ( Context) has many states and changes its behavior frequently depending on these states during the rest of its lifespan.
Like Strategy, if your Context object has many if...else
statements, this might be an indicator to use the State pattern.
The Template pattern defines the skeleton of an algorithm in the superclass and overrides specific steps of this algorithm by its subclasses without changing its structure.
From the diagram, we note that the superclass (Order) lets its subclasses override specific tasks of its algorithm. As a result, if we want to add a new payment gateway all we have to do is add a subclass that overrides these specific tasks.
So what is the difference between Strategy and Template design patterns?
- Strategy varies the entire algorithm via its strategies.
- Template varies specific parts of the algorithm by subclasses.
Let’s jump into our example:
From the previous example, we now deal directly with the subclasses which are responsible to run the template method (processOrder).
When should you use the Template design pattern?
You should use the Template pattern if you have an algorithm and you want to override specific steps (not the entire algorithm) of it with interchangeable subclasses.
So, what is the best pattern I have to use? As always, it depends, it is up to the developer who should understand the general concepts and the pros and cons of each pattern and as a result, decides what is better for his situation.
- Refactoring Guru
- Source Making
- Nodejs Design Patterns 3rd edition
If you liked this article please rate and share it to spread the word, really, that encourages me a lot to create more content like this.
If you found this article useful, check out these articles as well:
- Open-Closed Principle: The Hard Parts
- How To Use GraphQL Directives Efficiently?
- 4 Ways to Handle Async Operations in Javascript
- MongoDB GridFS, Made Simple
Thanks a lot for staying with me up till this point. I hope you enjoy reading this article.