If there was one all-powerful methodology to, say, managing a software project, then there wouldn't be a need to learn any of the others. The reality of project management though, as is true in much of the development industry, is knowing how to make compromises; depending on the situation, one approach might be more efficient than another. When you need to vary the strategy a program will use from one situation to the next, the strategy pattern is an obvious choice.

# What is the Strategy Pattern?

The strategy pattern is a behavioral design pattern that allows a class to use different algorithms at runtime.

<div style="width:100%; margin:auto;text-align:center;"><img src="https://www.devmaking.com/img/topics/designpatterns/StrategyPattern_01.png" alt="strategy pattern UML diagram" style="max-width:95%;"> </div>

A popular example of strategy design is being able to switch sorting algorithms on the fly: if list A is known to be mostly sorted, you might consider using one algorithm over another. Alternatively, if list B is know to be completely random, a different algorithm might be more efficient.

## Conceptualization

To best demonstrate the effectiveness of the strategy pattern, consider the following code; our class `ArraySorter` attempts to sort using different algorithms, however all of the algorithms are stored in a single file. The sorting method that will be used is decided by a string input:

### Before the strategy pattern:

``````class ArraySorter {
String sortingMethod;

void setMethod(String method) {
this.sortingMethod = method;
}

// Sort an array based on the current sorting method:
void sort(int[] arr) {
if(sortingMethod == "insertionSort") {
// Do insertion sort:
for ( int i = 0; i &lt; arr.length; i++ ) {
int tmp = arr[i];
int j = i - 1;
while ( j &gt;= 0 &amp;&amp; arr[j] &gt; tmp ) {
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = tmp;
}
}
else if(sortingMethod == "selectionSort") {
// Do selection sort:
for ( int i =0; i &lt; arr.length - 1; i++ ){
int min = i;
for ( int j = i + 1; j &lt; arr.length; j++ ){
if ( arr[j] &lt; arr[min] ){
min = j;
}
}
int tmp = arr[min];
arr[min] = arr[i];
arr[i] = tmp;
}
}
// and so on...
}
}
``````

Not only is this code bulky and difficult to understand, it would be a nightmare to maintain and extend with new sorting algorithms. Instead, we're going to utilize the following strategy pattern to give our code proper organization:

<div style="width:100%; margin:auto;text-align:center;"><img src="https://www.devmaking.com/img/topics/designpatterns/StrategyPattern_02.png" alt="array sorter strategy pattern UML diagram" style="max-width:95%;"> </div>

Using an interface `SortingStrategy`, our different algorithms will sort in their own classes implementing the interface. These classed can be called upon by the client and used in `ArraySorter` dynamically.

### After implementing Strategy

``````// Strategy interface:
interface SortingStrategy {
void sort(int[] arr);
}

// Concrete strategy 1:
class InsertionStrategy implements SortingStrategy {
void sort(int[] arr) {
// Do insertion sort:
for ( int i = 0; i &lt; arr.length; i++ ) {
int tmp = arr[i];
int j = i - 1;
while ( j &gt;= 0 &amp;&amp; arr[j] &gt; tmp ) {
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = tmp;
}
}

}
// Concrete strategy 2:
class SelectionStrategy implements SortingStrategy {
void sort(int[] arr) {
// Do selection sort:
for ( int i =0; i &lt; arr.length - 1; i++ ){
int min = i;
for ( int j = i + 1; j &lt; arr.length; j++ ){
if ( arr[j] &lt; arr[min] ){
min = j;
}
}
int tmp = arr[min];
arr[min] = arr[i];
arr[i] = tmp;
}
}
}

}

// Context class:
class ArraySorter {
// maintain a reference to a strategy:
SortingStrategy strategy;

ArraySorter() {
// Optional: set a default strategy in the constructor.
strategy = new InsertionStrategy();
}

// Set the strategy:
void setStrategy(SortingStrategy strategy) {
this.strategy = strategy;
}

// Executes the strategy:
void sort(int[] arr) {
strategy.sort(arr);
}
}
``````

Now our code is nice and organized! Additionally, if we wanted to implement new algorithms, we'd only need to define a new class implementing the `SortingStrategy` interface and it will work immediately in our application. This helps keep our code maintainable and reusable.

### Client Code:

``````static void main(String[] args) {
// array to sort:
int[] array = {8, 2, 65, 1, 97, 123, 6, 82, 4};

ArraySorter sorter = new ArraySorter();

String sortingMethod = args[0];

if(sortingMethod == "insertionSort") {
sorter.setStrategy(new InsertionStrategy());
}
else if(sortingMethod == "selectionSort") {
sorter.setStrategy(new SelectionStrategy());
}
// and so on...
else {
throw new Exception("Unrecognized sorting strategy!");
}
// sort the array:
sorter.sort(array);

String res;
for(i : array) {
res += i + " ";
}
print(res);
// Done!
}
``````

> Challenge: in you language of choice, extend the example with MergeSort and QuickSort!

### Output:

``````1 2 4 6 8 65 82 123
``````