Strategy Design Pattern tutorial with design diagrams and code examples.
o Better Way (Solving problem using “has a” instead of “is a”)
o Design diagram of strategy design pattern
Have you ever thought what the better approach between composition and inheritance is? And if you were given the opportunity to design software using either of these two methods, I’m sure most of you will stuck to inheritance. This is because we can easily think of our software in a hierarchical manner. But is it the best way for our software? Does it really support better maintenance?
Most likely some of you may still be confused weather we can use inheritance and composition interchangeably because they are two different concepts.
Well you don’t need to worry, just continue this tutorial and you will end up by grasping lots of important knowledge about designing software.
Think of a situation where you were asked to create a jungle. The most common approach would be to create an abstract Animal class with the intention of sub classing it to create other animals. (Note that Animal class is abstract because we don’t need anybody to instantiate Animal class. There are no Animal objects in real world).
Figure 1 – Abstract Animal Class
And we can create sub Classes as follows.
And we can refer to the Dog class as follows.
The output will result as “I’m Walking” as expected. And similarly other Classes will also provide the same result. And you are happy since that worked out pretty well.
But wait a minute. This just doesn’t seem to be right. This will result both Twitter’s and Goldfish’s go methods to output as I’m Walking which should be I’m Flying and I’m swimming respectively.
So what should we do to avoid this being happening? As most of you might have guessed we can override the go() method of both Twitter and Goldfish to provide their specific functions as follows.
Well now everything seems to be all right. J . What can go wrong!
WAIT! You haven’t solved anything instead messed everything up because you have thrown the code reuse (One of the most important factors to consider while designing software) out of the window.
In every level you just have to code special functionalities according to the requirements of the classes. Think when more and more animals come in to the Jungle you will have to code many different go() methods accordingly.
So what causes this problem and what is the possible answer? It just seem like there’s no answer to this problem because we have used the only possible answer. Actually not, we have to use composition over inheritance. Then the problem will be solved. Let’s consider that approach.
Better Way (Solving problem using “has a” instead of “is a”)
Can you recall the problem we had? It’s a very popular and unforgivable mistake that we have done. That is we were unable to separate the parts that tempt to change over time. We should separate those changeable parts from the rest of our application and reuse them as much as possible. That will result in an application that supports easy maintenance.Keep in mind that we should keep those codes that tempt to change as freestanding as possible to avoid major code changes that will affect core code changes as well.
In this case inheritance is the worst because it will spread the changeable codes over generations allowing the programmers to change them over many generations. We have to override the methods to our specific needs and in the next level we will have to override that code again to assist that particular class.
Therefore the best way is to extract out the go method and provide “has a” relationship to the corresponding classes. In this scenario we found several special go() methods namely goBYWalking(), goBYFlying(), goBySwimming(). So we can extract all these specific go methods out and link. In order to perform this we can provide the programmers a template by allowing them to subclass a go() method always. This approach will force a constraint for programmers to stick to same template throughout the project life.
Therefore the architect can provide an interface with go() method to be inherited by programmers to create specific go() methods and link them with corresponding classes. Go interface is shown follows.
Figure 3 – Go Interface
And the specific go() methods will be created by implementing the interface as follows.
Figure 4 – Specific Go Class
And now we will have to use these specific go methods inside each animal object and we at the design level should impose the constraint to use these methods at the implementation level. We will do this by providing a revised Animal class to the programmer that they will use to create Specific Animal objects. Revised abstract Animal Class has presented below.
Figure 5 – Revised Animal Class
Here, programmer can define the appropriate go() method to the particular Class in its constructor so every object will get the same go() method accordingly.
Figure 6 – Revised Dog Class
Design diagram of strategy design pattern
Therefore the Strategy design pattern to this specific problem can be illustrated as follows.