# 1. Definition

The Strategy Design Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

# 2. Problem Statement

Imagine you have a system that requires multiple ways to execute a particular action (e.g., sorting). Hardcoding each algorithm or using complex conditional logic can make the system rigid, less maintainable, and harder to extend.

# 3. Solution

Encapsulate each algorithm (or strategy) into separate classes with a common interface. This will allow you to switch algorithms or strategies on-the-fly without altering the code that uses them.

# 4. Real-World Use Cases

1. Different methods for calculating shipping costs.

2. Various strategies for compressing files.

3. Different AI behaviors in a game.

# 5. Implementation Steps

1. Define a strategy interface that describes how the strategies will be invoked.

2. Implement multiple concrete strategy classes based on the strategy interface.

3. Context class which uses a strategy should have a method to set the strategy, and then it can delegate the algorithmic work to the strategy object.

# 6. Implementation in Go

``````// Strategy interface
type SortingStrategy interface {
Sort(dataset []int) []int
}
// Concrete strategy 1: Bubble Sort
type BubbleSort struct {}
func (b *BubbleSort) Sort(dataset []int) []int {
// ... bubble sort algorithm ...
return dataset  // just for the sake of simplicity
}
// Concrete strategy 2: Quick Sort
type QuickSort struct {}
func (q *QuickSort) Sort(dataset []int) []int {
// ... quick sort algorithm ...
return dataset  // again, simplified
}
// Context class
type Sorter struct {
strategy SortingStrategy
}
func (s *Sorter) SetStrategy(strategy SortingStrategy) {
s.strategy = strategy
}
func (s *Sorter) ExecuteStrategy(dataset []int) []int {
return s.strategy.Sort(dataset)
}
// Client code
func main() {
data := []int{5, 3, 4, 1, 2}
sorter := &Sorter{}
// Use Bubble Sort
sorter.SetStrategy(&BubbleSort{})
sortedData := sorter.ExecuteStrategy(data)
fmt.Println("Bubble Sort:", sortedData)
// Switch to Quick Sort
sorter.SetStrategy(&QuickSort{})
sortedData = sorter.ExecuteStrategy(data)
fmt.Println("Quick Sort:", sortedData)
}
``````

### Output:

```Bubble Sort: [5, 3, 4, 1, 2]
Quick Sort: [5, 3, 4, 1, 2]
(Note: The output displays unsorted data for simplicity. In a real-world application, the data would be sorted.)
```

### Explanation:

1. The SortingStrategy interface defines a Sort method, which all concrete strategies must implement.

2. BubbleSort and QuickSort are concrete strategies that implement the SortingStrategy.

3. The Sorter context class allows you to set a strategy and then execute it.

4. In the client code, we set different strategies and execute them.

# 7. When to use?

Use the Strategy pattern when:

1. You want to define a class that can have one of a number of behaviors.

2. You need to switch algorithms or strategies at runtime.

3. You have a lot of conditional statements that choose different variations of an algorithm.