Strategy Pattern

So, as decided in the introduction post, let us start with the ritual of solving a problem without knowing anything about the pattern.

Problem Statement:

There is an Airtel tower in Model Town (with a limited coverage) that can support upto 50 users, maximum. Scheduling of users is a big research problem in telecom industry. 50 users need to be scheduled in certain order. For optimization and simplicity, suppose Airtel identifies that at any given time there can be two types/groups of users (based on the data service they are using) –

Group 1- users engaged in watsapp chatting

Group 2- users playing real time games.

Each group has it’s own set of attributes. Now, user groups need to be scheduled in some order from each group. Airtel want you to design the software of their scheduler such that  group 1 users are always scheduled in a Round Robin manner and group 2 users are scheduled using a delay sensitive scheduling algorithm (which is their propriety).

/* Note that I am using ‘Airtel’ only for illustrative purpose here, Airtel may/may not work on these principles. You can read ‘Airtel’ as any ‘ABC’ company for example. */

Getting Deeper:

First Insight to solving the problem would be to have a base class UserScheduler that contains a function schedule. Group1 and group2 classes will inherit the UserScheduler class and override the function schedule to implement round robin and delay-sensitive scheduling respectively. Wait, since UserScheduler class does not need to implement it’s own functions, it does not need to be instantiated and hence, it can be  made abstract.

The design looks like this-

 

strategy1.jpg

 

Enhancement Required:

Since the mobile applications increased, the users can be grouped into 9 categories based on the data service requirement. Now, they want you to design the software of their scheduler such that  –

Group 1 users are scheduled in RR manner

Group 2- Delay sensitive manner

Group 3- RR manner

Group 4- weighted RR manner

Group 5- Proportional fair manner

Group 6- RR manner

Group 7- weighted RR manner

Group 8 – Proportional Fair manner

Group 9 – Delay sensitive manner

Getting Deeper

Thought Process:

We can make 9 classes that implement the abstract base class. Each class would implement it’s own scheduling algorithm. Simple!

Wait, we can see same scheduling manner being used in multiple groups (or classes), this will make the code very redundant. In future if more groups arise, each using one of the 4 scheduling manners or even a newer one, redundancy will increase manifold.

Let us call these manners as algorithms. Currently, there are four scheduling algorithms- RR, weighted RR, Delay sensitive, Proportional Fair. There are 9 group of users, each can implement any one of the four algorithms. These numbers can be changed in future.

Idea:

Let us encapsulate algorithms separately and let these groups use the algorithms without knowing the details.

So, there will be one base class userScheduler that’ll be inherited by 9 groups of users, and 1 base class scheduler that’ll be inherited by 4 scheduling algorithms. The class userScheduler will use the scheduling algorithms, instead of inheriting them. The design looks like the following UML diagram (However, I’ll show only 2 groups and 2 scheduling algorithms in the diagram, rest can be made on similar lines)-

strategy2

The code looks like-

abstract class scheduler{

void schedule ();

}

class RoundRobin : public scheduler{

void schedule()  {

/*Implement RR scheduling algorithm*/

}

};

class DelaySensitive : public scheduler{

void schedule() {

/*Implement Delay Sensitive Algorithm*/

}

};

abstract class UserScheduler{

void scheduleUsingAlgorithm();

}

class Group_1_User : public UserScheduler{

private:

scheduler schedulerObj;

public:

Group_1_User(){

schedulerObj = new RoundRobin();

}

void scheduleUsingAlgorithm(){

schedulerObj.schedule();

}

};

class Group_2_User : public UserScheduler{

privte:

scheduler schedulerObj;

public:

Group_2_User(){

schedulerObj = new DelaySensitive();

}

void scheduleUsingAlgorithm(){

schedulerObj.schedule();

}

};

class Test{

UserScheduler group1= new Group_1_User();

group1.scheduleUsingAlgorithm();

UserScheduler group2= new Group_2_User();

group2.scheduleUsingAlgorithm();

};

This looks good!

Wait What?

Yet Another Enhancement Required:

Design it in a manner such that, group 1 users can switch from RR algorithm to DS algorithm dynamically.

Going deeper

Ummm… this is not much of an effort. We’ll do 3 things-

1. Create a setScheduler method in ‘UserScheduler’ class, that’ll set the scheduler object as RR or DS (which will be given as argument at run time).

2. Move the implementation of function ‘scheduleUsingAlgorithm’ into the class ‘UserScheduler’

3. Make ‘UserScheduler’ as a concrete superclass instead of an abstract class.

The code looks like-

abstract class scheduler{

void schedule ();

}

class RoundRobin : public scheduler{

void schedule()  {

/*Implement RR scheduling algorithm*/

}

};

class DelaySensitive : public scheduler{

void schedule() {

/*Implement Delay Sensitive Algorithm*/

}

};

class UserScheduler{

private:

char *listOfSelectedUsers;

scheduler schedulerObj;

public:

void setScheduler(scheduler *ob){

schedulerObj = ob;

}

void scheduleUsingAlgorithm(){

schedulerObj.scheduler();

}

};

class Group_1_User : public UserScheduler{

Group_1_User(){

scheduler rr = new RoundRobin();

}

};

class Group_2_User : public UserScheduler{

Group_1_User(){

scheduler rr = new DelaySensitive();

}

};

 

class Test{

UserScheduler group1= new Group_1_User();

group1.scheduleUsingAlgorithm(); /*By default, group1 will execute RR scheduling algorithm*/

group1.setScheduler(new DelaySensitive()); /*scheduling algorithm is changed here*/

group1.scheduleUsingAlgorithm();

};

This looks perfect!!

We’ve learned the Strategy Pattern.

Definition: The Strategy Pattern allows to

  1. define a set of algorithms
  2. Encapsulate the algorithms, each one separately.
  3. Select the algorithm at run time.

The class diagram, as given in Wikipedia looks as follows-

strategy3

Advantages:

  1. It gives the advantages of Open-Closed Principle in software designing. According to this principle, all software entities (classes, functions, modules etc) should be open for extension and closed for modification. Strategy Pattern provides flexibility by allowing clients to change the code by adding their own algorithms instead of changing the existing ones.
  2.  Allows to use different version of algorithms. A classical tradeoff in implementation is an algorithm that provides time efficiency and the one that provides space efficiency. Using Strategy Pattern, the choice of which algorithm to use can be delegated to the user.
  3. Allows users to switch between different algorithms at run time.

A Perplexing Consequence:

  1. The Algorithms usually require data to be passed from the context class. This should be done carefully. Context and the Strategy classes normally communicate through the abstract Strategy base class. Strategy base class must expose all the required behaviours, which some concrete Strategy classes might not implement.

 

Save

Published by:

Neha Katyal

I am a research enthusiast, a software developer, a passionate writer and a seeker. From researching on various aspects of software design, to designing and developing 4G/5G algorithms, everything excites me. Besides my inclination towards software, I have a strong interest in spirituality. I am a seeker; learning yoga, meditation, aura cleansing, Vedic astrology, reading Vedic scriptures that can bring me closer to the ultimate truth, are a few things that has formed an integral part of my life. Apart from these, writing, reading fiction and sketching are the places where I find my home. I cannot just pass a bookstore, I cannot come out of a storm until I write a poem, I cannot admire an actor/actress until I sketch their portrait. Yes, I can be called as a 'multipotentialite'. I love to learn a lot, travel, imagine, read, write, draw, design, code, engage in dhyana and yog, serve others, spend time with family. Because, I feel, life is all about learning, falling, rising, feeling, enjoying every moment :-)

Categories Software DesignLeave a comment

Leave a comment