What is a Strategy Design Pattern
The Strategy pattern is useful when there is a set of related algorithms and a client object needs to be able to dynamically pick and choose an algorithm from this set that suits its current need.
In software development, the Strategy design pattern allows for the dynamic selection and interchangeability of algorithms at runtime.
The Strategy design pattern is a behavioral design pattern that allows you to define a family of algorithms, encapsulate each one of them, and make them interchangeable at runtime. It enables the client to choose the appropriate algorithm without tightly coupling the client code to specific implementations.
The Strategy pattern suggests keeping the implementation of each of the algorithms in a separate class. Each such algorithm encapsulated in a separate class is referred to as a strategy. An object that uses a Strategy object is often referred to as a context object.
Explanation
Strategy pattern is used when we have multiple algorithms for a specific task and client decides the actual implementation to be used at runtime. Strategy pattern is also known as Policy Pattern. We define multiple algorithms and let client application pass the algorithm to be used as a parameter.
One of the best example of this pattern is Collections.sort () method that takes Comparator parameter. Based on the different implementations of Comparator interfaces, the Objects are getting sorted in different ways.
Key Features of the Strategy Design Pattern:
- Context: The context represents the object that interacts with the strategy objects. It contains a reference to the current strategy and uses it to perform the desired operation.
- Strategy Interface / Abstract class : The strategy interface or abstract class defines the common methods that encapsulate different algorithms. It provides a contract for all concrete strategy implementations.
- Concrete Strategies: Concrete strategy classes implement the strategy interface or extend the strategy abstract class. Each concrete strategy encapsulates a specific algorithm.
- Client: The client code creates an instance of the context and sets the desired strategy. It uses the context to perform operations without needing to know the specifics of the strategy.
NOTE –
The strategy pattern is one way that composition can be used as an alternative to subclassing. Rather than providing different behaviors via subclasses overriding methods in super classes, the strategy pattern allows different behaviors to be placed in Concrete Strategy classes which share the common Strategy interface.
A Context object contains a reference to a Strategy. By changing the Context’s Strategy, different behaviors can be obtained.
Examples
- java.util.Comparator#compare ()
- javax.servlet.http.HttpServlet
- javax.servlet.Filter#doFilter ()
Implementation
Create the Strategy interface
// Strategy interface
interface SortingStrategy {
void sort(int[] array);
}
Implement concrete sorting strategies
// ConcreteStrategyA
class BubbleSort implements SortingStrategy {
@Override
public void sort(int[] array) {
// Implementation of Bubble Sort
System.out.println("Sorting using Bubble Sort");
}
}
// ConcreteStrategyB
class MergeSort implements SortingStrategy {
@Override
public void sort(int[] array) {
// Implementation of Merge Sort
System.out.println("Sorting using Merge Sort");
}
}
Create a Context class that will use the strategies
// Context class
class SortingContext {
// Context contains a reference to the strategy
private SortingStrategy strategy;
public void setStrategy(SortingStrategy strategy) {
this.strategy = strategy;
}
public void sortArray(int[] array) {
strategy.sort(array);
}
}
Client code / Demo
public class Main {
public static void main(String[] args) {
int[] data = {5, 2, 7, 1, 3};
SortingContext context = new SortingContext();
// Use BubbleSort
context.setStrategy(new BubbleSort());
context.sortArray(data);
// Use MergeSort
context.setStrategy(new MergeSort());
context.sortArray(data);
}
}
Output :
Sorting using Bubble Sort Sorting using Merge Sort
In this example, we have two concrete sorting strategies, BubbleSort and MergeSort, that implement the SortingStrategy interface. The SortingContext class is the context that uses these sorting strategies. At runtime, you can change the sorting strategy used by the context by calling setStrategy() with the appropriate concrete strategy.
The Strategy pattern provides a flexible way to define interchangeable algorithms, making the code more maintainable and scalable. It is often used in scenarios where different variations of an algorithm need to be supported or when you want to allow the client to choose a specific behavior dynamically.
In Java, the Strategy pattern can be applied in various scenarios where different algorithms need to be selected and used dynamically.
Use cases
Use the Strategy pattern when:
- Many related classes differ only in their behavior. Strategies provide a way to configure a class with one of many behaviors.
- You need different variants of an algorithm. For example, you might define algorithms
reflecting different space/time trade-offs. Strategies can be used when these variants are implemented as a class hierarchy of algorithms. - An algorithm uses data that clients shouldn’t know about. Use the Strategy pattern to
avoid exposing complex, algorithm-specific data structures. - A class defines many behaviors, and these appear as multiple conditional statements in
its operations. Instead of many conditionals, move related conditional branches into their own Strategy class.