Strategy Design Pattern

Learn via video courses

Abstract

Strategy Design Pattern is a behavioral design pattern. It works by abstracting out that part of a class code that is prone to changes into a strategy, which can dynamically be injected at runtime

When will we need a Strategy design pattern?

To understand the strategy pattern in a lucid manner, let us take an example of a Martial Arts game you wish to develop. This game allows players to select a fighter of different martial arts styles. Let us assume Judo, Karate, KungFu are some of them

All these forms implement a common superclass called MartialArt

Some of the basic functions we expect a fighter to make are kick(), punch() and grab(). Let us assume the basic functionalities to do so are defined in the superclass

Now the requirement is that Judo fighters do not kick or punch, but only grab. This is how we will implement the same:

Here arises the first problem with this design: Problem 1: Whenever any type of martial art does not wish to implement some basic method, they have to override it to do nothing

Now let us say the Karate and KungFu fighters have a special type of kick called flying kick. Both the classes now need to override the kick method to do a flying kick

Here arises the second problem with this design: Problem 2: Multiple classes need to be touched to edit the common functionality among them, and we move away from the benefits of inheritance and introduce duplication in the code

Here is where a basic principle of OO design comes into play: Abstract out the part of your code that is susceptible to changes from the part which remains constant

How does the Strategy Design Pattern work?

In our fighting game example, the kick function is something that can change for different fighting styles. We can also anticipate that punch and grab might have different behaviours based on the fighting style

We can create two concrete classes for each type of kicking strategy

Now that we have extracted the KickStrategy out of our fighter classes, we can use composition to inject the strategy into fighter classes

We can make our code even easier to modify, by programming to the interface rather than the implementation. If tomorrow KungFu fighters want to kick in a different style, we can do so at runtime using polymorphism rather than edit the classes every time

Thus if later we decide that a KungFy fighter needs a new type of kick called rotating kick, we just need to pass that strategy to its constructor;

If any fighter does not wish to kick, we can simply implement the KickStrategy to do nothing

This pattern of abstracting out the strategy of doing a method from the entity classes, and setting it polymorphically at runtime, is the Strategy Design Pattern

We can now summarize the above design changes in a class diagram

Strategy Design Pattern

Note that we can make the superclass MartialArt abstract, and specify the default implementation for kick(), punch(), grab() in the abstract class. Fighters that wish to stick to the default implementation can just re-use the code

Pros and Cons of Strategy Design pattern

Pros:

  1. We can avoid using conditionals like switch if-else statements to decide the behaviour of entity classes at run time
  2. The main behavioural algorithms are abstracted out from the main context entities These advantages make our code easy to maintain and extensible

Cons:

  1. Since we have abstracted out the behaviour of context entities from their classes, the onus is on the client to understand various strategies to implement the behaviours, and pass it accordingly
  2. We will end up creating more objects in our application, demanding more memory footprint

Difference between Strategy and Factory Design Pattern

StrategyFactory
It is a behavioural design patternIt is a creational design pattern
It determines how objects will behave at runtimeIt determines how the objects will be created at runtime
Using strategy pattern we can determine how will a fighter kick/ punch/ grabUsing factory pattern we can determine how will a fighter be created in the first place

FAQ

  1. How do I know I should use the Strategy Design Pattern?
    Strategy pattern should be used when you have a use case of deciding how your objects will behave dynamically. In scenarios where you have a lot of classes with some of them having similar behaviour for few methods, and in the future you plan to change this behaviour frequently, Strategy pattern will help you achieve reusability and extensibility in your code.

  2. Why do we use composition?
    As a thumb rule, hasA relationships are more flexible than isA relationships. Composition allows you to change the behaviour of your classes at runtime. You also end up encapsulating the set of algorithms that determine the behaviour of classes into the classes themselves