Monday, March 30, 2015

Strategy Design Pattern in Java using Enum - Tutorial Example

Strategy Design Pattern in Java using Enum - Tutorial Example

I have said this before that Java Enum is very versatile and can do lot more than you normally expect from it. We have seen lot of examples of Enum in my earlier posts e.g. writing thread-safe Singleton using Enum and 10 ways to use Enum in Java. In this article, we will  learn a new way to use Enum, for implementing Strategy design pattern. Strategy pattern is one of the famous pattern, which takes advantage of polymorphism, to remove switch cases and strive for open close design principle. Formally it encapsulate related algorithm, known as strategy and make them interchangeable. So your Client, also known as Context, can use different algorithm or strategy, without any modification. One of the key advantage of Strategy pattern is it's extensibility, i.e. introducing new Strategy is as easy as writing a new class and implementing Strategy interface, with Enum, instead of creating separate class, you creates a separate Enum instance, which means less number of classes and full benefit if Strategy pattern.



How to implement Strategy pattern using Enum in Java

In this tutorial, we will see an example of implementing Strategy pattern using Java Enum, I would use a sporting example. If you are cricket fan, like me, you are going to connect with this article, but  if you are a Soccer or Tennis fan, than let me explain a bit about example. In Cricket, there are three popular formats T20 (20 over match), One day(50 over match) and Test(5 days match). If a player, plays all three format, he needs to adjust it's batting strategy to be effective. For example, T20 is all about scoring quickly, while One day international games give bit of time for setting and then scoring. In contrast of shorter version, Test match is all about grinding i.e. occupying crease and making sure your opponent get tired, before scoring briskly. In our Strategy pattern example, we have use an Enum to define different batting strategy. We have defined a default play() method and since, Enum can override methods, we are overriding it on every instances i.e. on T20, ONE_DAY and TEST. Our context class, which is named as Player also has a play() method, which delegates to play() method of configurable Strategy.


UML diagram of Strategy Design Pattern

Here is the UML diagram of Strategy pattern in Java, Why you should draw UML diagram? because this is the best way to remember and understand how a design pattern works. In fact, this is the standard ways to communicate your design to your fellow developers and team members.

UML diagram of Strategy Design Pattern in Java
In this diagram, I have explained strategy design pattern using sorting algorithm e.g. Bubble Sort, QuickSort, Insertion Sort  and Selection Sort. For our code example, you can replace Strategy interface with Match, and sorting strategy to T20, OneDay and Test Matches.


Strategy Pattern Example using Enum

Here is full code example of implementing Strategy design pattern using Enum in Java. If you are coding in Eclipse IDE then you don't need to do much, just select and copy this code, select the Java project you are working in Eclipse IDE and paste it. Eclipse will take care of creating right packages and source file with proper name e.g. name of public class. This is the quickest way to try and execute Java code snippet from internet in your IDE. Also remember, Strategy pattern is a good example of Open Closed Design Principle of SOLID object oriented design principle.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Java program to demonstrate that Enum can be used to implement Strategy
* Pattern in Java.
*
* @author Javin
*/
public class Match {

private static final Logger logger = LoggerFactory.getLogger(Match.class);

public static void main(String args[]) {

Player ctx = new Player(Strategy.T20);
ctx.play();

ctx.setStrategy(Strategy.ONE_DAY);
ctx.play();

ctx.setStrategy(Strategy.TEST);
ctx.play();

}


}

/*
* Player class, which uses different Strategy implementation.
*/
class Player{
private Strategy battingStrategy;

public Player(Strategy battingStrategy){
this.battingStrategy = battingStrategy;
}

public void setStrategy(Strategy newStrategy){
this.battingStrategy = newStrategy;
}

public void play(){
battingStrategy.play();
}
}

/*
* An Enum to implement Strategy design pattern in Java. Different instances of
* Enum represent different batting strategy, based upon type of game e.g. T20,
* One day international or Test match.
*/
enum Strategy {

/* Make sure to score quickly on T20 games */
T20 {

@Override
public void play() {
System.out.printf("In %s, If it's in the V, make sure it goes to tree %n", name());
}
},

/* Make a balance between attach and defence in One day */
ONE_DAY {

@Override
public void play() {
System.out.printf("In %s, Push it for Single %n", name());
}
},

/* Test match is all about occupying the crease and grinding opposition */
TEST {

@Override
public void play() {
System.out.printf("In %s, Grind them hard %n", name());
}
};

public void play() {
System.out.printf("In Cricket, Play as per Merit of Ball %n");
}
}

Output:
In T20, If it's in the V, make sure it goes to tree
In ONE_DAY, Push it for Single
In TEST, Grind them hard


That's all on How to implement Strategy design pattern in Java using Enum. You can see that it's lot easier to implement Strategy pattern with Enum, you not only reduced number of classes, but also achieves extensibility and flexibility of Strategy pattern. On down side, Yes, you need to change your tried and tested Enum every time, though by inserting only new code, it's still violate Open Closed principle a bit, which advocates that new functionality should be added by writing new code, rather than modifying existing code.

No comments:

Post a Comment