Strategy Pattern is one of the behavioral design patterns. The strategy pattern, in computer programming, is also known as policy pattern. It makes it possible to select an algorithm at run-time. The strategy pattern is responsible for defining a family of algorithms, encapsulating every algorithm and making the algorithms capable of interchanging themselves within the family of algorithms.
The strategy pattern was added in the highly influential book, Design Patterns by Gamma et.al. This book made popular the concept of design patterns usage in computer programming; object-oriented programming to design, versatile and reusable object-oriented software.
Strategy Pattern
According to the Gang of Four:
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
For example, if a class were to perform a validation on incoming data, it could approach the strategy pattern in order to select a validation algorithm, on account for the type of the data received, the source by which the data was received, the choice of the user or any other differentiating factors. These factors are not recognized until run-time and may additionally require completely different validation to be performed. It is possible for the different validating objects in the system or even different regions of the system, to be able to use the validation algorithms or strategies because the strategies are encased separately from the validating objects. This can be done without having to duplicate the code.
also read:
Implementing the Strategy Pattern
To implement the strategy pattern, the most important requirement is to be able to hold a reference to the same code in the data structure and be able to retrieve it. There are different mechanisms to achieve this, which are; native function pointer, the first class function, by gaining access to the internal storage of the code of implementation language using reflection method, classes or class instances in object-oriented programming.
To design, versatile and reusable object-oriented software, there is 23 well-known Gang of Four (GoF) design patterns, the strategy behavioral pattern is one of them. There are some problems that strategy pattern caters. A class is supposed to be configured using an algorithm, it is not supposed to be implementing an algorithm explicitly. An algorithm must be chosen and interchanged at a run-time. Algorithms are defined as a method or procedure which takes in an input value, operate some operations on the value, perform some steps on it and produces an output value. Generally, it is said to be a piece of code which performs appropriate operations.
Spring 5 Design Pattern Book
To implement an algorithm explicitly in the class which uses the algorithm, it creates inflexibility, because it tightly couples the class to a certain algorithm at compile-time and in turn makes it difficult, almost impossible to alter the algorithm later, without having to alter the class. Due to this problem, the class is no longer reusable for any other algorithm that is to be used. The strategy pattern is responsible for defining a separate object which encloses an algorithm, which means it defines an interface for executing an algorithm. It is also able to define classes which perform the algorithms in various ways. A strategy object is assigned an algorithm at run-time by a Class.
Benefits of the Strategy Pattern:
There are following lists the benefits of using the Strategy pattern:
- This pattern allows you to create the related classes with difference their behavior.
- This pattern provide a group of interchangable algorithms.
- It provides an alternate of subclassing
- It reduce complexity because it defines each behavior in its own class, so it eliminates conditional statements.
UML Class Diagram for Strategy Design Pattern
Let’s see the following UML diagram is showing the all components of Strategy design pattern:
Strategy
It is an interface, it is common to all strategies or algorithms, Suppose a SortStrategy in the application.
ConcreteStrategy
It is implementation of Strategy interface, it implements the algorithm using the Strategy. Suppose QuickSort, MergeSort etc are implementation of SortStrategy interface.
Context
It is a class that configured with a ConcreteStrategy object. Its behavior depedends on the state of Strategy. Suppose if you change QuickSort to MergeSort then behavior of context object changed accordingly as like SortedList.
Example for Strategy Design Pattern Implementation
This real-world code demonstrates the Strategy pattern which encapsulates sorting algorithms in the form of sorting objects. This allows clients to dynamically change sorting strategies including Quicksort, Shellsort, and Mergesort.
Step 1: Create an interface.
SortStrategy.java
/** * */ package com.doj.patterns.strategy.state; import java.util.List; /** * @author Dinesh.Rajput * */ public interface SortStrategy { void sort(List list); }
Step 2: Create concrete classes implementing the same interface.
QuickSort.java
/** * */ package com.doj.patterns.strategy.state; import java.util.Comparator; import java.util.List; /** * @author Dinesh.Rajput * */ public class QuickSort implements SortStrategy { @Override public void sort(List list) { //Implementing quick sort here list.sort(new Comparator() { @Override public int compare(String o1, String o2) { return o1.compareTo(o2); } }); System.out.println("QuickSorted list "); } }
MergeSort.java
/** * */ package com.doj.patterns.strategy.state; import java.util.List; /** * @author Dinesh.Rajput * */ public class MergeSort implements SortStrategy { @Override public void sort(List list) { //Implement merge sort here System.out.println("MergeSorted list "); } }
ShellSort.java
/** * */ package com.doj.patterns.strategy.state; import java.util.List; /** * @author Dinesh.Rajput * */ public class ShellSort implements SortStrategy { @Override public void sort(List list) { //Implement ShellSort Here System.out.println("ShellSorted list "); } }
Step 3: Create Context Class.
SortedList.java
/** * */ package com.doj.patterns.strategy.state; import java.util.ArrayList; import java.util.List; /** * @author Dinesh.Rajput * */ public class SortedList { private List _list = new ArrayList<>(); private SortStrategy _sortstrategy; public void SetSortStrategy(SortStrategy sortstrategy){ this._sortstrategy = sortstrategy; } public void add(String name){ _list.add(name); } public void sort(){ _sortstrategy.sort(_list); // Iterate over list and display results for(String name : _list) { System.out.println(" " + name); } System.out.println(); } }
Step 4: Use the Context to see change in behavior when it changes its Strategy.
StrategyPatternDemo.java
/** * */ package com.doj.patterns.strategy.state; /** * @author Dinesh.Rajput * */ public class StrategyPatternDemo { /** * @param args */ public static void main(String[] args) { // Two contexts following different strategies SortedList userRecords = new SortedList(); userRecords.add("Dinesh"); userRecords.add("Arnav"); userRecords.add("Anamika"); userRecords.add("Vinesh"); userRecords.add("Adesh"); userRecords.SetSortStrategy(new QuickSort()); userRecords.sort(); userRecords.SetSortStrategy(new ShellSort()); userRecords.sort(); userRecords.SetSortStrategy(new MergeSort()); userRecords.sort(); } }
Step 5: Let’s run the demo class and verify the output.
QuickSorted list Adesh Anamika Arnav Dinesh Vinesh ShellSorted list Adesh Anamika Arnav Dinesh Vinesh MergeSorted list Adesh Anamika Arnav Dinesh Vinesh