Что такое паттерн "Стратегия" (Strategy)

Стратегия — поведенческий паттерн проектирования, который позволяет выбирать алгоритм поведения объекта во время выполнения. Вместо жёстко прописанного алгоритма, объект делегирует задачу одному из семейства алгоритмов.

Представьте, что у вас есть приложение, которое может сортировать данные разными способами: быстрой сортировкой, сортировкой слиянием или пузырьком. Паттерн Стратегия позволяет легко переключать алгоритмы сортировки без изменения клиента.

Преимущества паттерна «Стратегия»

  • Изоляция алгоритмов, упрощение их замены и расширения.
  • Упрощение поддержки и тестирования каждого алгоритма отдельно.
  • Повышение гибкости системы.

Пример:

  • Контекст — объект, который использует алгоритм.
  • Стратегии — отдельные классы, реализующие разные алгоритмы.
  • Контекст делегирует выполнение задачи выбранной стратегии.

Где применяется паттерн «Стратегия»?

  • При выборе алгоритма на основе условий во время выполнения.
  • В системах с вариативными бизнес-правилами.
  • Для замены условных операторов выбора поведения.

Пример реализации на JavaScript

// Интерфейс стратегии class Strategy { execute(data) { throw new Error("Метод execute() должен быть реализован"); } } // Конкретные стратегии class BubbleSortStrategy extends Strategy { execute(data) { console.log("Сортировка пузырьком"); // Пример простой сортировки пузырьком for (let i = 0; i < data.length; i++) { for (let j = 0; j < data.length - i - 1; j++) { if (data[j] > data[j + 1]) { [data[j], data[j + 1]] = [data[j + 1], data[j]]; } } } return data; } } class QuickSortStrategy extends Strategy { execute(data) { console.log("Быстрая сортировка"); if (data.length <= 1) return data; const pivot = data[0]; const left = data.slice(1).filter((el) => el < pivot); const right = data.slice(1).filter((el) => el >= pivot); return [...this.execute(left), pivot, ...this.execute(right)]; } } // Контекст class Sorter { constructor(strategy) { this.strategy = strategy; } setStrategy(strategy) { this.strategy = strategy; } sort(data) { return this.strategy.execute(data); } } // Использование const sorter = new Sorter(new BubbleSortStrategy()); console.log(sorter.sort([5, 3, 8, 1])); sorter.setStrategy(new QuickSortStrategy()); console.log(sorter.sort([5, 3, 8, 1]));

Когда стоит использовать паттерн «Стратегия»?

  • Когда нужно менять алгоритмы во время выполнения.
  • Чтобы избежать большого количества условных операторов.
  • Для инкапсуляции алгоритмов и повышения гибкости.

Отличие от других паттернов

  • В отличие от Шаблонного метода, Стратегия делегирует весь алгоритм отдельным классам.
  • Отличается от Состояния тем, что выбор стратегии обычно контролируется клиентом, а не внутренним состоянием объекта.

Плюсы паттерна

  • Улучшает читаемость и расширяемость кода.
  • Легко добавлять новые алгоритмы.
  • Способствует принципу открытости/закрытости (OCP).

Минусы паттерна

  • Увеличивает количество классов.
  • Клиент должен знать о различных стратегиях.