Strategy Pattern in Java with Example

Can you tell me any design pattern which you have used recently in your project, except Singleton? This is one of the popular questions from various Java interviews in recent years. I think this actually motivated many Java programmers to explore more design patterns and actually look at the original 23 patterns introduced by GOF. Strategy pattern is one of the useful patterns you can mention while answering such a question. It's very popular, and there are lots of real-world scenarios where the Strategy pattern is very handy. Many programmers ask me what the best way to learn design patterns is, I say you first need to find how other people use it and for that, you need to look at the open-source libraries you use in your daily task. JDK API is one such library I use on a daily basis, and that's why when I explore new algorithms, design patterns, I first search JDK for their usage.

The strategy pattern has found its place in JDK, and you know what I mean if you have sorted ArrayList in Java. Yes, a combination of Comparator, Comparable, and Collections.sort() method is one of the best real-world examples of the Strategy design pattern.

To understand it more, let's first find out what Strategy pattern is? The first clue is the name itself.  The strategy pattern defines a family of related algorithms l sorting algorithms like the bubble sort, quicksort, insertion sort and merges sort, or compression algorithm e.g. zip, gzip, tar, jar, encryption algorithm e.g. MD 5, AES, etc and lets the algorithm vary independently from clients that use it.

For example, you can use the Strategy pattern to implement a method that sort numbers and allows the client to choose any sorting algorithm at runtime, without modifying the client's code. So essentially Strategy pattern provides flexibility, extensible, and choice. You should consider using this pattern when you need to select an algorithm at runtime.

In Java, a strategy is usually implemented by creating a hierarchy of classes that extend from a base interface known as Strategy. In this tutorial, we will learn some interesting things about the Strategy pattern by writing a Java program and demonstrating how it adds value to your code.

And, If you are serious about learning design patterns and principles, I suggest you take a look at the Design Patterns in Java course on Udemy. This course covers both SOLID design principles like Open Closed and Liskov substitution, and all-important Object Oriented design patterns like Decorator, Observer, Chain of Responsibility, and much more





What is the Intent of the Strategy Design Pattern?

While learning a new pattern, the most important thing to understand is intent, motivation. Why? because two design patterns can have the same structure but their intent could be totally different. Even, one of a good example of this theory is State and Strategy pattern.

If you look at the UML diagram of these two patterns they look identical but the intent of the State pattern is to facilitate state transition while the intent of the Strategy pattern is to change the behavior of a class by changing the internal algorithm at runtime without modifying the class itself.  That's why the Strategy pattern is part of behavioral patterns in GOF's original list.

You can correlate Strategy pattern with how people use a different strategy to deal with a different situation, for example, if you are confronted with a situation then you will either deal with it or run away two different strategies.

If you have not read already then you should also read the Head First Design pattern, one of the best books to learn the practical use of design patterns in Java application. Most of my knowledge of GOF design patterns are attributed to this book. It's been 10 years since the book was first released, thankfully it is now updated to cover Java SE 8 as well.





Terminology and Structure of the Strategy Pattern

This pattern has two main components, Strategy interface, and Context class. Strategy interface declares the type of algorithm, it can be an abstract class or interface. For example, you can define a Strategy interface with method move(), now this move becomes strategy and different pieces in a game of chess can implement this method to define their moving strategy.

For example, Rook will move only horizontal or vertical, Bishop will move diagonally, Pawn will move one cell at a time and Queen can move horizontal, vertical and diagonally.  The different strategy employed by different pieces for movement is an implementation of Strategy interface and the code which moves pieces is our Context class.

When we change the piece, we don't need to change the Context class. If a new piece is added, then also your code which takes care of moving pieces will not require to be modified.

Here is the UML diagram of Strategy pattern :
Strategy Design Pattern Implementation in Java



Pros and Cons of Strategy Pattern

Every algorithm or pattern has some advantages and disadvantage and this pattern is also no different. The main benefit of using the Strategy pattern is flexibility. The client can choose any algorithm at run time, you can easily add new Strategy without modifying classes that use strategies e.g. Context. This becomes possible because the Strategy pattern is based upon the Open Closed design principle, which says that new behavior is added by writing a new code not by modifying the tried and tested old code.

If you use the Strategy pattern, you will be adding a new Strategy by writing a new class that just needs to implement the Strategy interface. Because of the open-closed principle violation, we cannot use Enum to implement the Strategy pattern.

Though it has some advantages and suits well if you know major algorithms well in advance you need to modify your Enum class to add new algorithms which is a violation of open-closed principle. To learn more see here.


Real-World Examples of Strategy Design Pattern

JDK has a couple of examples of this pattern, first is Collection.sort(List, Comparator) method, where Comparator is Strategy and Collections.sort() is Context. Because of this pattern, your sort method can sort any object, the object which doesn't exist when this method was written. As long as, Object will implement the Comparator interface (Strategy interface), Collections.sort() method will sort it.

Another example is  java.util.Arrays#sort(T[], Comparator < ? super T > c) method which similar to Collections.sort() method, except need array in place of List.

You can also see the classic Head First Design pattern book for more real-world examples of Strategy and other GOF patterns.


Strategy Pattern Implementation in Java

Here is a simple Java program that implements a Strategy design pattern. You can use this sample code to learn and experiment with this pattern. The example is very simple, all it does is define a strategy interface for sorting algorithms and use that interface on a method called arrange.

This method can arrange objects in increasing or decreasing order, depending upon how you implement. In order to arrange an object, you need sorting and this is provided by a Strategy pattern. This allows you to choose any algorithm to sort your object.


/**
 * Java Program to implement Strategy design pattern in Java. 
 * Strategy pattern allows you to supply different strategy without
 * changing the Context class, which uses that strategy. You can
 * also introduce new sorting strategy any time. Similar example
 * is Collections.sort() method, which accept Comparator or Comparable
 * which is actually a Strategy to compare objects in Java.
 * 
 * @author WINDOWS 8
 */

public class Test {

    public static void main(String args[]) throws InterruptedException {
        
        // we can provide any strategy to do the sorting 
        int[] var = {1, 2, 3, 4, 5 };
        Context ctx = new Context(new BubbleSort());
        ctx.arrange(var);
        
        // we can change the strategy without changing Context class
        ctx = new Context(new QuickSort());
        ctx.arrange(var);
    }

}

interface Strategy {
    public void sort(int[] numbers);
}

class BubbleSort implements Strategy {

    @Override
    public void sort(int[] numbers) {
        System.out.println("sorting array using bubble sort strategy");

    }

}

class InsertionSort implements Strategy {

    @Override
    public void sort(int[] numbers) {
        System.out.println("sorting array using insertion sort strategy");

    }
}

class QuickSort implements Strategy {

    @Override
    public void sort(int[] numbers) {
        System.out.println("sorting array using quick sort strategy");

    }
}

class MergeSort implements Strategy {

    @Override
    public void sort(int[] numbers) {
        System.out.println("sorting array using merge sort strategy");

    }
}

class Context {
    private final Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public void arrange(int[] input) {
        strategy.sort(input);
    }
}

Output
sorting array using bubble sort strategy
sorting array using quick sort strategy




Things to Remember about Strategy Pattern in Java

Now let's revise what you have learned in this tutorial about the strategy design pattern  :

1) This pattern defines a set of related algorithm and encapsulate them in separated classes, and allows the client to choose any algorithm at run time.

2) It allows adding a new algorithm without modifying existing algorithms or context class, which uses algorithms or strategies.

3) The strategy is a behavioral pattern in the GOF list.

4) The strategy pattern is based upon the Open Closed design principle of SOLID Principles of Object-Oriented Design.

5) Collections.sort() and Comparator interface is a real-world example of the Strategy pattern.


That's all about how to implement the Strategy pattern in Java. For your practice write a Java program to implement encoding and allow the client to choose between different encoding algorithms like base 64. This pattern is also very useful when you have a situation where you need to behave differently depending upon type like writing a method to process trades if trades are of type NEW,  it will be processed differently, if it is CANCEL then it will be processed differently and if its AMEND then also it will be handled differently, but remember each time we need to process trade.


Further Learning
Design Pattern Library
From 0 to 1: Design Patterns - 24 That Matter - In Java
Java Design Patterns - The Complete Masterclass
SOLID Principles of Object-Oriented Design


Other Java Design Patterns tutorials you may like
  • Top 5 Courses to learn Design Pattern in Java (courses)
  • 5 Free Courses to learn Object Oriented Programming (courses)
  • Difference between Factory and Dependency Injection Pattern? (answer)
  • Top 5 Courses to learn Microservices in Java with Spring (courses)
  • How to create thread-safe Singleton in Java? (example)
  • How to implement the Strategy Design Pattern in Java? (example)
  • Difference between Factory and AbstractFactory Pattern? (example)
  • 18 Java Design Pattern Interview Questions with Answers (list)
  • How to design a Vending Machine in Java? (questions)
  • 20 System Design Interview Questions (list)
  • Difference between State and Strategy Design Pattern in Java? (answer)
  • Top 5 Courses to learn Design Patterns in Java (courses)
  • 5 Free Courses to learn Data Structure and Algorithms (courses)
  • My favorite courses to learn Software Architecture (courses)

Thanks for reading this article so far. If you like these design pattern interview questions then please share with your friends and colleagues. If you have any questions or feedback then please drop a note.

P. S. - If you are looking for some free courses to learn Design Pattern and Software Architecture, I also suggest you check out the Java Design Patterns and Architecture course by John Purcell on Udemy. It's completely free, all you need to do is create an Udemy account to access this course. 

6 comments:

  1. Strategy is my favorite pattern and we keep finding it usages everywhere. Couple of days back, I have to code discount rates based upon COUPON type, and guess what? I used Strategy pattern. It make it very easy to introduce a new coupon type with a differnet discounted rate without modifying billing engine code.

    ReplyDelete
  2. Can you please explain some drawbacks of Strategy pattern? This was asked to me on recent interview and I only manage to tell that it require lot of classes .... Interviewer not very impressed.

    ReplyDelete
  3. "Because of open closed principle violation, we cannot use Enum to implement Strategy pattern. Though it has some advantage and suits well if you know major algorithm well in advance but you need to modify your Enum class to add new algorithms which is violation of open closed principle."

    Why would it be a problem to add an entry into an Enum as we have to rebuild the whole module/project to add the new implementation of the Strategy interface, and very often also add some user description of the new algorithm (so that a user can choose this strategy instead of another) ?

    ReplyDelete
  4. can you please explain the command pattern

    ReplyDelete
  5. There is slight wrong implementation. In diagram, you showed context implements Strategy interface, while in the coding you have used a different method 'arrange'.

    ReplyDelete
    Replies
    1. Hello Anonymous, context doesn't implement Strategy, it actually holds a reference to Strategy interface to perform the task.

      Delete