What is the Strategy Design Pattern?
The Strategy Design Pattern is a behavioral design pattern that allows you to define a family of algorithms or behaviors, put each of them in a separate class, and make them interchangeable at runtime. This pattern is useful when you want to dynamically change the behavior of a class without modifying its code.
Characteristics of this design pattern
This pattern exhibits several key characteristics, such as:
Defines a family of algorithms: The pattern allows you to encapsulate multiple algorithms or behaviors into separate classes, known as strategies.
Encapsulates behaviors: Each strategy encapsulates a specific behavior or algorithm, providing a clean and modular way to manage different variations or implementations.
Enables dynamic behavior switching: The pattern enables clients to switch between different strategies at runtime, allowing for flexible and dynamic behavior changes.
Promotes object collaboration: The pattern encourages collaboration between a context object and strategy objects, where the context delegates the execution of a behavior to a strategy object.

1. Context
A class or object known as the Context assigns the task to a strategy object and contains a reference to it.
It serves as an intermediary between the client and the strategy, offering an integrated approach for task execution without exposing every detail of the process.
The Context maintains a reference to a strategy object and calls its methods to perform the task, allowing for interchangeable strategies to be used.
2. Strategy Interface
An abstract class or interface known as the Strategy Interface specifies a set of methods that all concrete strategies must implement.
As a kind of agreement, it guarantees that all strategies follow the same set of rules and are interchangeable by the Context.
The Strategy Interface promotes flexibility and modularity in the design by establishing a common interface that enables decoupling between the Context and the specific strategies.
3. Concrete Strategies
Concrete Strategies are the various implementations of the Strategy Interface. Each concrete strategy provides a specific algorithm or behavior for performing the task defined by the Strategy Interface.
Concrete strategies encapsulate the details of their respective algorithms and provide a method for executing the task.
They are interchangeable and can be selected and configured by the client based on the requirements of the task.
4. Client
The Client is responsible for selecting and configuring the appropriate strategy and providing it to the Context.
It knows the requirements of the task and decides which strategy to use based on those requirements.
The client creates an instance of the desired concrete strategy and passes it to the Context, enabling the Context to use the selected strategy to perform the task.
How Strategy Pattern helps to solve above challenges?
Here’s how the Strategy Pattern helps:
Code Reusability: By encapsulating sorting algorithms into separate strategy classes, you can reuse these strategies across different parts of the system. This reduces code duplication and promotes maintainability.
Flexibility and Extensibility: The Strategy Pattern makes it simple to adapt or add new sorting algorithms without changing the existing code. Since each strategy is independent, it is possible to change or expand it without impacting other system components.
Separation of Concerns: The Strategy Pattern separates sorting logic into distinct strategy classes, which encourages a clear division of responsibilities. As a result, the code is easier to test, and maintain.

Below is the implementation of the above example:
1. Context(SortingContext)
public class SortingContext {
private SortingStrategy sortingStrategy;
public SortingContext(SortingStrategy sortingStrategy) {
this.sortingStrategy = sortingStrategy;
}
public void setSortingStrategy(SortingStrategy sortingStrategy) {
this.sortingStrategy = sortingStrategy;
}
public void performSort(int[] array) {
sortingStrategy.sort(array);
}
}
2. Strategy Interface(SortingStrategy)
public interface SortingStrategy {
void sort(int[] array);
}3. Concrete Strategies
// BubbleSortStrategy
public class BubbleSortStrategy implements SortingStrategy {
@Override
public void sort(int[] array) {
// Implement Bubble Sort algorithm
System.out.println("Sorting using Bubble Sort");
}
}
// MergeSortStrategy
public class MergeSortStrategy implements SortingStrategy {
@Override
public void sort(int[] array) {
// Implement Merge Sort algorithm
System.out.println("Sorting using Merge Sort");
}
}
// QuickSortStrategy
public class QuickSortStrategy implements SortingStrategy {
@Override
public void sort(int[] array) {
// Implement Quick Sort algorithm
System.out.println("Sorting using Quick Sort");
}
}4. Client Component
public class Client {
public static void main(String[] args) {
// Create SortingContext with BubbleSortStrategy
SortingContext sortingContext = new SortingContext(new BubbleSortStrategy());
int[] array1 = {5, 2, 9, 1, 5};
sortingContext.performSort(array1); // Output: Sorting using Bubble Sort
// Change strategy to MergeSortStrategy
sortingContext.setSortingStrategy(new MergeSortStrategy());
int[] array2 = {8, 3, 7, 4, 2};
sortingContext.performSort(array2); // Output: Sorting using Merge Sort
// Change strategy to QuickSortStrategy
sortingContext.setSortingStrategy(new QuickSortStrategy());
int[] array3 = {6, 1, 3, 9, 5};
sortingContext.performSort(array3); // Output: Sorting using Quick Sort
}
}Output
Sorting using Bubble Sort
Sorting using Merge Sort
Sorting using Quick Sort
Advantages
Open/Closed Principle: New strategies can be added without modifying existing code.
Encapsulation: Each algorithm is encapsulated in its own class, making it easier to maintain and extend.
Flexibility: The client can switch algorithms at runtime.
Disadvantages
Complexity: Increases the number of classes in the system.
Overhead: Slight performance overhead due to dynamic delegation.
Real-World Analogy
Think of a navigation app (like Google Maps) where you can choose a mode of transport: driving, walking, or biking. Each mode has a different algorithm for calculating the route. The navigation app (context) dynamically selects the mode of transport (strategy) based on user input.
Conclusion
The Strategy Design Pattern is a powerful tool for writing flexible and maintainable code. It separates the algorithm from the client, making it easy to switch and extend algorithms dynamically. This pattern is highly useful in systems requiring dynamic behavior modification.