Introduction to Design Patterns :
Design patterns are proven solutions to recurring problems in software design. They are best practices that help developers solve common design issues in a flexible, reusable, and efficient manner. Design patterns are not code but templates that guide developers in creating scalable and maintainable software. They are typically categorized into three main types:
1.) Creational Patterns : Deal with object creation mechanisms (e.g., Singleton, Factory Method).
2.) Structural Patterns : Focus on composing classes and objects to form larger structures (e.g., Adapter, Decorator).
3.) Behavioral Patterns : Address how objects interact and communicate (e.g., Strategy, Observer).
Among these, the Strategy Design Pattern stands out as a key behavioral pattern that provides flexibility by enabling dynamic selection of algorithms at runtime.
Strategy Design Pattern :
The Strategy Design Pattern is a behavioral design pattern that allows you to define a family of algorithms, encapsulate each one, and make them interchangeable. The pattern enables a class's behavior to be selected at runtime without modifying its structure, promoting flexibility and adherence to the Open/Closed Principle (OCP).
When to Use the Strategy Design Pattern ?
Key Components :
1.) Strategy Interface : Defines the common behavior (algorithm).
2.) Concrete Strategy Classes : Implement the various versions of the algorithm.
3.) Context Class : Maintains a reference to a Strategy and delegates execution to it.
4.) Client : The Client is responsible for selecting and configuring the appropriate strategy and providing it to the Context.
Communication between the Components :
1.) Client to Context :
2.) Context to Strategy :
3.) Strategy to Context :
4.) Strategy Interface as Contract :
5.) Decoupled Communication :
Class Diagram :

Complete Code 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
}
}5.) Output :
Sorting using Bubble Sort
Sorting using Merge Sort
Sorting using Quick SortBenefits of the Strategy Design Pattern :
Drawbacks of The Strategy Design Principle :