Strategy (Стратегия)
Шаблон проектирования "Стратегия" (Strategy) позволяет определять семейство алгоритмов, инкапсулировать каждый из них и делать их взаимозаменяемыми. Этот паттерн позволяет изменять алгоритмы независимо от клиентов, которые их используют.
Основные компоненты паттерна "Стратегия":
- Контекст (Context): класс, который использует стратегию.
- Стратегия (Strategy): интерфейс, который определяет общий метод для всех конкретных стратегий.
- Конкретные стратегии (Concrete Strategies): классы, реализующие интерфейс стратегии.
Пример на Java
Рассмотрим пример, в котором у нас есть разные способы сортировки массива чисел. Мы создадим интерфейс SortingStrategy
, который будет определять метод сортировки, и несколько конкретных стратегий, таких как BubbleSort
и QuickSort
.
// Интерфейс стратегии
interface SortingStrategy {
void sort(int[] array);
}
// Конкретная стратегия: Пузырьковая сортировка
class BubbleSort implements SortingStrategy {
@Override
public void sort(int[] array) {
int n = array.length;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (array[j] > array[j + 1]) {
// меняем местами
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
}
}
// Конкретная стратегия: Быстрая сортировка
class QuickSort implements SortingStrategy {
@Override
public void sort(int[] array) {
quickSort(array, 0, array.length - 1);
}
private void quickSort(int[] array, int low, int high) {
if (low < high) {
int pi = partition(array, low, high);
quickSort(array, low, pi - 1);
quickSort(array, pi + 1, high);
}
}
private int partition(int[] array, int low, int high) {
int pivot = array[high];
int i = (low - 1);
for (int j = low; j < high; j++) {
if (array[j] < pivot) {
i++;
// меняем местами
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
int temp = array[i + 1];
array[i + 1] = array[high];
array[high] = temp;
return i + 1;
}
}
// Контекст
class Sorter {
private SortingStrategy strategy;
public Sorter(SortingStrategy strategy) {
this.strategy = strategy;
}
public void setStrategy(SortingStrategy strategy) {
this.strategy = strategy;
}
public void sort(int[] array) {
strategy.sort(array);
}
}
// Пример использования
public class StrategyPatternExample {
public static void main(String[] args) {
int[] array = {5, 2, 9, 1, 5, 6};
Sorter sorter = new Sorter(new BubbleSort());
System.out.println("Сортировка пузырьком:");
sorter.sort(array);
System.out.println(java.util.Arrays.toString(array));
// Изменяем стратегию на быструю сортировку
array = new int[]{5, 2, 9, 1, 5, 6}; // Сбрасываем массив
sorter.setStrategy(new QuickSort());
System.out.println("Быстрая сортировка:");
sorter.sort(array);
System.out.println(java.util.Arrays.toString(array));
}
}
Объяснение кода:
- Интерфейс
SortingStrategy
определяет методsort
, который будет реализован конкретными стратегиями. - Классы
BubbleSort
иQuickSort
реализуют интерфейсSortingStrategy
и предоставляют свои алгоритмы сортировки. - Класс
Sorter
является контекстом, который использует стратегию. Он может менять стратегию в любое время с помощью методаsetStrategy
. - В методе
main
мы создаем экземплярSorter
с одной стратегией, выполняем сортировку, затем меняем стратегию и снова выполняем сортировку.
Таким образом, паттерн "Стратегия" позволяет легко добавлять новые алгоритмы сортировки, не изменяя код клиента.