Overview Of Strategy Design Pattern

Let’s first understand the meaning of Strategy.

A strategy is a plan of actions towards achieving specific goals. Let’s try to understand this with a real-life example.

We take a car to reach the office, we call it Strategy1.
Strategy Design Pattern

Now, due to some problem, our car is in a garage or let's say, a family member has taken it. For tackling such a situation, we will use the Bus Strategy to reach office. We call it Strategy2.

Strategy Design Pattern 

However, the story doesn’t end here... what if the bus services are down?

Now, a new strategy called the Train Strategy can come into the scenario.

Strategy Design Pattern 

The Strategy Pattern does the same thing that we have done in the above example. A strategy can be replaced by another one at any point of time. So in the above example, we used Car Strategy initially and then due to some issues, we replaced it with Bus and then Train.

Now, let's see the definition of Strategy Pattern as per "Gang of Four".

Gang of Four says, "Define a family of algorithms, encapsulate each one, and make them interchangeable."

Strategy lets the algorithm vary independently from a client that uses it. It helps us to solve the design problems for designing flexible and reusable in object-oriented software, i.e., objects which are easier to implement, change, test, and reuse.

Now, let’s have a real-life example of Sales Application which accepts bill amount and calculates the final bill amount by applying the discount depending on the day of the week. Suppose it is Monday, then 20% of discount is provided. And if it is Wednesday, then a 50% flat discount is offered but there is no discount on any other day.

Now, let’s create clsSales class which will encapsulate the below things.

  • Bill Amount
  • Calculate Final Bill Amount which will return bill amount after applying an appropriate discount on the basis of week’s day.

    Strategy Design Pattern

Now, if we keep calculating bill amount logic inside clsSales and there are any changes in the discount, then we have to modify the clsSales class which violets "Open Close" principle along with it. We cannot reuse the login if we want to use it somewhere else.

To overcome this issue, we will move the discount logic outside of clsSlaes.

Strategy Design Pattern

Here, we are implementing all discount calculations on the basis of different strategies using Strategy Pattern. Now, let’s look into the source code.

We need to create an interface which will act as the base of all the strategies.

  1. public interface IStrategy  
  2. {  
  3.     double GetFinalBill(double billAmt);  
  4. }  

Now, we need to create all the strategies related to discount.

We will first create Less Discount strategy as shown below.

  1. public class LessDiscountStrategy : IStrategy  
  2.     {  
  3.   
  4.         public double GetFinalBill(double billAmt)  
  5.         {  
  6.             return Convert.ToDouble(billAmt - (billAmt * 0.2));  
  7.         }  
  8.     }  

In the above code, we have implemented GetFinalBill by inheriting it from IStrategy which returns the final bill by providing 20% discount.

Now, let's move to another strategy, i.e., High Discount Strategy, as shown below.

  1. public class HighDiscountStrategy : IStrategy  
  2.     {  
  3.         public double GetFinalBill(double billAmt)  
  4.         {  
  5.             return  Convert.ToDouble( billAmt - (billAmt * 0.5));  
  6.         }  
  7.     }  

In the above code, we are providing 50% discount by implementing GetFinalBill from IStrategy.

Let’s move to the last one, i.e., No Discount Strategy.

  1. public class NoDiscountStrategy : IStrategy  
  2.     {  
  3.         public double GetFinalBill(double billAmt)  
  4.         {  
  5.             return Convert.ToDouble(billAmt);  
  6.         }  
  7.     }  

Similarly, in the above code, we have provided no discount.

Let's  use a Strategy for which we will create class ClsSales.

  1. public class ClsSales  
  2.   {  
  3.       public double billAmt { get; set; }  
  4.   
  5.       StrategyPattern.IStrategy currentStrategy;  
  6.       public ClsSales(IStrategy newStrategy)  
  7.       {  
  8.           currentStrategy = newStrategy;  
  9.       }  
  10.   
  11.       public double GetFinalBill()  
  12.       {  
  13.           return currentStrategy.GetFinalBill(billAmt);  
  14.       }  
  15.   }  

In the above example, we have created ClsSales class which is accepting bill amount from the client and current strategy in the constructor and accordingly, it is returning the final bill amount on the basis of strategy.  In other words, it is internally using strategy for applying discount.

Now, let's use ClsSlaes class as shown below.

  1. class Program  
  2.     {  
  3.         static void Main(string[] args)  
  4.         {  
  5.             ClsSales sales = new ClsSales(null);  
  6.             Console.WriteLine("Enter 1 for Monday and 4 for Wednesday");   
  7.             int day = Convert.ToInt32(Console.ReadLine());  
  8.             switch (day)  
  9.             {  
  10.                 case 1:  
  11.              sales = new ClsSales(new LessDiscountStrategy());  
  12.                     break;  
  13.                 case 4:  
  14.                     sales = new ClsSales(new HighDiscountStrategy());  
  15.   
  16.                     break;  
  17.                 default:  
  18.                     sales = new ClsSales(new NoDiscountStrategy());  
  19.                     break;  
  20.             }  
  21.             sales.billAmt = 1000;  
  22.   
  23.             Console.WriteLine("Total Bill " + sales.GetFinalBill());  
  24.             Console.ReadLine();  
  25.         }  
  26.     }  

In the above example, we are creating an instance of ClsSales class by passing separate strategy on the basis of day entered by the user.