Design Patterns- Strategy
Design patterns are typical solutions to common problems in software design. Each pattern is like a blueprint that you can customize to solve a particular design problem in your code.
One of the biggest benefits of the design patterns is that it gives developers a common vocabulary to talk about software solutions. It does define a common language which can be understood by developers all over the world
There is a task to design a duck pond simulation game. The game can show a large variety of duck species swimming and making a quacking sound. The old and obvious approach would be Object-oriented, where we can design a class called Duck as superclass and all the other duck types will inherit from it. That solves our problem. isn’t it? Let's see through implementation.
Now a new requirement comes and that is — Ducks need to fly!!!
How will we incorporate flying into our current design? As we are using inheritance here, we can directly put the flying method in the superclass(Duck) and all the other duck types can directly use it.
Just like this:
So looks Great right? But there is a huge problem with this design, suppose there are rubber ducks which got introduced, which in real can’t fly. But with this design approach, they still will have fly() functionality as they will inherit the same superclass. This breaks the Interface Segregation principle also where our duck is forced to implement the flying functionality. The most we can do is override the fly method in rubber duck class and let it be empty. But suppose if we are maintaining a large number of species then it would become very difficult to maintain the code.
So what should we do to avoid this problem?
First, we have to identify what is causing a problem? In this case, it’s a fly method as not all the ducks can fly, so the solution is to separate it out from the Duck class and encapsulate in another data structure and then use it. We should make sure that all other functionality remains the same as they are already well structured and working perfectly fine.
We know that fly() and quack() are the parts of the duck class that vary across ducks.
To Separate these behaviors from the duck class, we will pull out both methods from the Duck Class and create a new set of classes to represent each behavior.
This makes it reusable too. We will have classes which conform or implement these behaviors and can be used with the duck class. So let’s see how we can implement them. See the below diagram to understand.
With these type of behaviors, other types of object (except duck object) can also use these behaviors as these are not hidden in Just one Duck class, this makes the reusability very high.
And even we can add or modify behaviors without even touching the Duck classes.
Now let's implement it using our Code in Swift.
Let’s Create the behaviors first
Now we have behaviors set up, let create classes which implements these behaviors. (These are called Strategies too)
For Quacking -
Now that we have all the required protocols and classes set up, let’s create the duck classes. Let’s create the superclass first.
This duck class has fly and quack behaviors which can be initialized by respecting duck classes like this below.
How to use them?. Let’s see below…
What’s the output?…
I can’t fly
So here we are, have solved a problem using Strategy Pattern. I am leaving you with the definition of Strategy pattern in one sentence.
Strategy pattern is also known as Policy Pattern. We define multiple algorithms and let client application pass the algorithm to be used as a parameter.
That’s it for this post, will see you in the next one!!
Reference: Head First Design Patterns (A Book By Eric Freeman)