9.5K views
10 bookmarked

# Create reusable component of partially common operation (method) using Strategy Design Pattern - Keep It Simple Series

## Introduction

Before we start. Let me answer the below questions.

What is the problem?
Why we need Strategy Design Pattern in order to solve the problem?

Let me explain the problem by taking one example. There is one superclass – S. It has four subclasses – A, B, C, and D. There is one operation (you can say a method) O, which has two versions of implementation. One version of an operation O is common to subclasses – A and C. Another version of an operation O is common to subclasses – B and D. We cannot simply put this operation O in super class S as operation O has two versions of implementation and these two versions are not common to all the subclasses. Each version of an operation O is partially common.

One Solution

We can implement a specific needed version of an operation O to each subclass. But here we are repeating ourselves. A good design doesn’t have repetition. Repetition makes the system hard to maintain, hard to extend and vulnerable to bugs. So, this solution is not a perfect solution.

Much Cleaner Solution

Use Strategy Design Pattern!

Don’t worry if you still don’t get the problem. We will discuss this throughout the article.
Now let’s understand how our superhero Strategy Design Pattern will save our day.

## Background

There is one simple Bird encyclopedia system. It simulates the bird's behaviour like flying, swimming, etc. Under the hood, there is one bird engine, which makes all these things possible. Let's discuss an initial design of the bird engine. There is one superclass called `Bird`. It is an `abstract` class and has all the common operation (method) implementation. There are three concrete classes of birds - `Swan``Albatross` and `Gull`, which inherits the `Bird` class. Let's see the diagram so we can understand things better. Please note one thing here, we never go to code level nitty-gritty details as it is a design article. Keep it simple.

As per the above diagram:

`Bird` class has the following operations (methods):

• `fly()`: Implementation of flying logic
• `swim()`: Implementation of swimming logic
• `walk()`: Implementation of walking logic
• `makeSomeNoise()`: It is an abstract (an operation without implementation, just a skeleton) operation. Every bird has a unique voice. So, every subclass has to provide its own implementation
• `display()`: It is an abstract operation. Every bird has a unique appearance. So, every subclass has to provide its own implementation.

`Swan` class has the following operations:

• `makeSomeNoise()`: Implementation of swan voice
• `display()`: Implementation of swan appearance

and the same thing for `Albatross` and `Gull` classes.

All the common bird operations are defined in Bird superclass. So that we don't need to repeat ourselves in concrete bird classes. A good design always encourages reusability.

## Problem Arises

Change is the only constant in the software industry. Now in bird engine, we need to add one another `bird` class called - `Penguin`. `Penguin` class has to inherit `Bird` class as per our design. So, `Penguin` class inherits all the operations of Bird class. But the problem is `Bird` class has `fly()` operation and our poor penguin cannot fly. Unless penguin is Skipper from Madagascar. What should we do now?

We can pull out `fly()` operation from `Bird` class and implement it to all concrete subclasses - `Swan`, `Albatross` and `Gull`. But if we do that, then we compromise reusability and we are repeating ourselves in all the concrete subclasses including `Penguin` class. As `Penguin` class should implement `fly()` operation with no fly implementation.

So, what should we do in order to solve the problem in a cleaner way?

## Solution Sunshine

In order to solve this problem in a cleaner way, we pull out the implementation of `fly()` operation from `Bird` class. Then we create one `FlyBehaviour` abstract class and define a `fly()` abstract operation in it.

`FlyBehaviour` abstract class has the following abstract operation:

• `fly()`: It is an abstract operation as we have two versions of `fly()` operation.

Then we define two concrete subclasses - `CanFly` and `CannotFly`, which inherit `FlyBehaviour` abstract class.

`CanFly` class has the following operations:

• `fly()`: Implementation of a bird flying

`CannotFly` class has the following operations:

• `fly()`: Do nothing as it is for those birds, who can't fly.

Let's see the updated diagram instead of making things more complex.

Here, `FlyBehaviour` is an interface as it doesn't have an implementation.

`Bird` abstract class structure updated only:

• `flyBehaviour`: It is an attribute of a type `FlyBehaviour`. It can hold `CanFly` or `CannotFly` concrete types. It can be set by `setFlyBehaviour()` operation.
• `setFlyBehaviour()`: It sets a concrete subclass type of `FlyBehaviour` to the `flyBehaviour` attribute. If concrete `Bird` type is `Penguin`, then `flyBehaviour` should be set to `CannotFly` type. For other concrete `Bird` types, `flyBehaviour` should be set to `CanFly` type.
• `fly()`: Now, this operation just calls the `fly()` operation on `flyBehaviour` attribute. Underlying concrete type (`CanFly` or `CannotFly`) of `FlyBehaviour` handles the operation behaviour.

This is called composition. Composition of `Bird` type and `FlyBheaviour` type. Identify the aspects of your application that vary and separate them from what stays the same. This way, we can create a resuable component of partially common operation.

## Another Problem Arises

Now we need to add one more bird to our bird engine called - `Frigatebird`. So, our `Frigatebird` class has to inherit `Bird` class as per design. So, `Frigatebird `class inherits all the operations of `Bird` class. But the problem is our poor `Frigatebird` can't swim. What should we do now?

You better know what we should do now. Try to solve this problem by yourself. you can find its solution right below but don't do cheating.

## Solution Sunshine Again

I am not going to repeat myself again. So I let the diagram speak as you know:

Quote:

A picture is worth a thousand words.

## Conclusion

The design solution that we have used in order to create a reusable component of the partially common operation is called - Strategy Design Pattern. Now our bird engine design is so flexible, that we can add more concrete bird types without changing other classes. All we need to do is just add class, that's it. Every engine should be designed in such a way that it encourages reusability, extensibility and maintainability. At the end of the day, a good design will save you lots of effort and lots of money also. The goal of each and every design pattern is to create a reusable, extendable and maintainable system.

Now it is a time of official definition of Strategy Design Pattern: Defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

## References

• Head First Design Patterns by O'Reilly