Strategy Design Pattern

Share

 

Strategy Design Pattern is one of the most easiest and powerful design patterns which if used properly at the right situation can bring enormous benefits to the code. Let us first understand what exactly it is all about with the help of a very simple example and later we will learn about all advantages and disadvantages of using it.

Understanding Strategy Design Pattern:  Let’s say – a developer has been asked to write code for a very specific and a special requirement: where the requirement is:

A customer can pay his bill in the Restaurant via Debit card,via cash and via Check. While making payment, the customer should choose one of these three payment strategies/options for paying bill. So, how you would write code for such a simple requirement ?There are many ways to tackle such a problem: One straight forward way as suggested by Strategy Design Pattern is as follows:

Create an Interface with the name IPaymentStrategy:

 

Interface IPaymentStrategy {

                 public void pay(int billAmount);

}

and, then create concrete classes implementing this Interface for all supported payment strategies/behaviour options :

 

public class DebitCardStrategy implements IPaymentStrategy {
       @Override
       public void pay(int billAmount) {
              System.out.println("Charging "+amount+" using Debit Card...");
              System.out.println("Thank you!!");");
       }
}

public class CashStrategy implements IPaymentStrategy {
       @Override
       public void pay(int billAmount) {
              System.out.println("Charged "+amount+" using Cash...");
              System.out.println("Thank you!!");");
       }
}

public class CheckStrategy implements IPaymentStrategy {
       @Override
       public void pay(int billAmount) {
              System.out.println("Charging "+amount+" using Check...");
              System.out.println("Thank you!!");");
       }
}

now, create a Customer class which has the IPaymentStrategy Interface declared as follows:

public class Customer {
       private IPaymentStrategy paymentStrategy;

       public Customer(IPaymentStrategy paymentStrategy) {
              this.paymentStrategy = paymentStrategy;
       }
       public void pay(int billAmount) {
              paymentStrategy.pay(billAmount);
       }
}

Now, let’s write a test class to test the above code:


public class TestClass {
        public static void main(String[] args) {
                Customer customer1 =
                         new Customer(new DebitCardStrategy());
                customer1.pay(1000);

                Customer customer2 =
                         new Customer(new CashStrategy());
                customer2.pay(5000);
       }
}

That is it!! we have just used Strategy Design Pattern to implement this simple requirement: The Pattern definition says:

Whenever you have a situation where a client is going to use a class whose behaviour (also, called as strategy) he can set/change depending upon his needs at runtime – than such a requirement can be well coded using the Strategy Design Pattern in the similar way as we did above.

In general, following are the steps to write code for such a requirement as suggested by the Strategy Design Pattern:

1. Create an Interface for the strategy/behaviour which client is going to set/change as per his needs at runtime while using a given class. [IPaymentStrategy.java ]

2. Create concrete classes implementing this interface for all supported Strategies/behaviours. [DebitCardStrategy.java, CashStrategy.java, CheckStrategy.java]

3. Declare the interface in the given class and allow client to set/change its value either through the constructor of the given class or by including a setter method  in the given class. [in the above example, I declared IPaymentStrategy interface in the Customer class and allowed client to set its value through the Customer class’s constructor]

That is it. Now, any client programme can  make use of the given class by simply setting its behaviour/strategy at runtime [the way I used in the test class above]

Below is the formal definition of Strategy Design Pattern which is mentioned in original GOF Design Patterns book ( Elements of Reusable OO Software):

Define a family of algorithms (also, called as behaviours or strategies), encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

[ it’s full explanation is what we saw above, however, if you find any difficulty to understand it in any ways… please put all your queries in the comments section below]

Some important points to note about Strategy Design Pattern:

1. Strategy Design Pattern is a Behavioral design Pattern.

2. UML diagram for the example we coded using Strategy Design Pattern is as follows:

UML Diagram of Strategy Design Pattern

UML Diagram of Strategy Design Pattern

In general, the given class whose behaviour client is going to set at runtime is called as the context [Customer class in the above example], the Strategy/behaviour interface is called as a strategy [IPaymentStrategy interface in the above example], and, all classes implementing strategy interface are called as ConcreteStrategies [DebitCardStrategy, CashStrategy, CheckStrategy in the above example]

3. We may tweak this pattern in our software projects as per our requirement just to keep things simpler. In the example above: I could have written Customer class as follows and still I would say it is based on Strategy Design Pattern. Earlier version of Customer class saves IPaymentStrategy value in paymentStrategy reference and this version does not; and every time customer pays bill he has to provide two arguments to it i.e. billAmount and paymentStrategy

public class Customer {
       public void pay(int billAmount, IPaymentStrategy paymentStrategy) {
              paymentStrategy.pay(billAmount);
       }
}

4. The most famous examples of code snippets implementing Strategy Design Pattern in Java Programming language are: Collections.sort() and Arrays.sort() – Both sort methods take two parameters 1) the collection object to be sorted 2) a comparator object i.e the concrete Strategy object [Just see the source code of Collections.sort and Arrays.sort and you will find it implemented using Strategy Design Pattern]

Note: Your all queries/thoughts on Strategy Design Pattern are welcome; please provide them in the comments section below and get a chance to enrol free of cost for an online Live Design Patterns course (specially designed for interview preparation for software companies like Amazon, Google, Facebook, FlipKart, SnapDeal, HealthKart…)