Lets say we have a simple application that executes certain actions dictated by an external service.
More particular the external service sends a response that looks like this:
the supported actions are:
and there is an executor to help as translate the response to an actual action execution:
This is an implementation of the Strategy Pattern where every strategy is a certain action allowing us to add as many actions as we want as long as there is a one-to-one relation with what the response sends:
One day the external service decides to add a print error action but it does not do it by having a new action value. Instead it decides to have an is error flag which must be taken under consideration when the action value is print!
So the response is now this:
leading us into having an
if in the print action’s code
which defeats the purpose of the strategy pattern and violates the SRP. Each strategy should do one thing and one thing only. By having an if in the strategy we allow it to implement two actions thus having two reasons to change.
Adding a chain
What we need is a way to allow the representation of a single action value from multiple strategies where each one implements a unique action depending on the values of the response.
This is where the Chain of Responsibility Pattern comes in helping as into having multiple actions tied together, passing the response to each other until one of them can execute it.
There are two ways to implement the pattern depending on the size and state of your project.
If you have a small project with just a few actions and you don’t mind touching many files you can use inheritance and have each action containing the next in the chain:
which can be used as such:
If we do not wish to change any of the existing actions then composition is the only way.
What we need is a way to wrap an existing action in an object that will (a) hold the next action in the chain and (b) decide which action will be executed, the wrapped or the next one:
ChainAction results in this:
This way we can scale the strategy pattern both vertically, one strategy per action value, and horizontally, one strategy per action value sub cases.