Applying the Strategy Pattern in Java

Working with strategy on Arrays.sort & java.util.Comparator

All these examples and more can be found on github
In Java, you cannot pass function references through a method. With this being true, how do we then apply a strategy to a method? What is suggested, is that we define an interface with the function we want to pass. This way we can on the fly, define and pass an algorithm to a method for process.

In this demo, we will be working strictly with the strategy interface: java.util.Comparator. This is a java strategy interface, readily available in the Java API as of 1.5. It supplies a compare algorithm, where its implementation is primarily for sorting large collections of objects.


Here is a look at the Comparator interface.

One primary strategy pattern in Java, uses the comparator for sorting arrays in some form or fashion. You can call Arrays.sort(array, comparator) to organize an array of objects based on a certain compare rule. With this implementation, you pass in your array object to sort, and the strategy algorithm to determine how to compare objects when sorting.



Simple Example of Sort Strategy

Here I would like to show an example of using the strategy pattern. First we will define an interface of type animal, and an implementing class. This is the object we will use for adding to an array and sorting the array.


Finally in the main,  we can build the animal list, supply our compare strategy, and print the ordered Array to console.
And the output:
Taking a closer look at the Comparator

In this example, we are using the Strategy Pattern for sorting an Array of animals by the animals Class type. The comparator algorithm follows a certain set of rules defined by the Java Team.
When comparing the objects, using compare, you want:
  • Equal objects to return 0
  • Different objects to either return a positive or negative integer depending on priority. 
In our case we aren't as
concerned about the final exact order of the objects, we just want to ensure that like Animals classes are grouped together.

So in our algorithm, we ensure that:
  1. Equal animal classes return a 0 compare; 
  2. Animal classes with different hash codes return some value greater than or less than the compared animals classes hash code.
This logic, ensures that an order will occur where: Animal classes with larger hash codes will be at the top of the list, and smaller hash codes at the bottom. All we really care about, is that the Animals are grouped by class. We use hash code comparison to ensure that the distinct rules of the compare algorithm are satisfied.

Using a concrete strategy
Sometimes, we have a strategy, that we need to apply often. In this case, it may be best to supply it as a concrete strategy. This is done, by defining and instantiating your strategy at the top of a class.

Here is an example of a singleton class holding static strategies for animal sorting.

To understand more about why I chose an Enum as a singleton, please take a look at my article on why Enum's make the best singletons.

Implementing Comparable's compare to strategy
With our concrete strategy, species sort, we can use the inherited compareTo method from interface Comparable. String class implements this method and ensures larger strings return negative, and smaller strings return positive values.

This is an example call to the concrete strategy:
Arrays.sort(animals, AnimalListStrategy.INSTANCE.speciesStrategyFunc);

Conclusion
In java we can consider that strategies are supplied by strategy objects. These objects should implement some strategy interface allowing implementation to depend on the needs of the client.

To see the final results, feel free to pull down the source code from github. This project will be updated with Java best practice concepts and examples. There is no UI, but you can run the main class RunAnimalStrategyDemo.java to test the strategy demo.

Comments

Popular posts from this blog

Atmosphere Websockets & Comet with Spring MVC

Microservices Tech Stack with Spring and Vert.X