Skip to content

Strategy (Стратегия)

Шаблон проектирования "Стратегия" (Strategy) позволяет определять семейство алгоритмов, инкапсулировать каждый из них и делать их взаимозаменяемыми. Этот паттерн позволяет изменять алгоритмы независимо от клиентов, которые их используют.

Основные компоненты паттерна "Стратегия":

  1. Контекст (Context): класс, который использует стратегию.
  2. Стратегия (Strategy): интерфейс, который определяет общий метод для всех конкретных стратегий.
  3. Конкретные стратегии (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));
    }
}

Объяснение кода:

  1. Интерфейс SortingStrategy определяет метод sort, который будет реализован конкретными стратегиями.
  2. Классы BubbleSort и QuickSort реализуют интерфейс SortingStrategy и предоставляют свои алгоритмы сортировки.
  3. Класс Sorter является контекстом, который использует стратегию. Он может менять стратегию в любое время с помощью метода setStrategy.
  4. В методе main мы создаем экземпляр Sorter с одной стратегией, выполняем сортировку, затем меняем стратегию и снова выполняем сортировку.

Таким образом, паттерн "Стратегия" позволяет легко добавлять новые алгоритмы сортировки, не изменяя код клиента.