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

«Что такое паттерн проектирования Strategy (Стратегия)?» — вопрос из категории Паттерны, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Strategy (Стратегия) — это поведенческий паттерн, который определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми. Он позволяет изменять алгоритм независимо от клиента, который его использует.

Проблема: Класс содержит множество условных операторов (if/switch), которые выбирают один из многих вариантов поведения.

Решение: Вынести каждое поведение в отдельный класс и сделать их взаимозаменяемыми.

Пример на Swift (Сортировка):

// 1. Интерфейс Стратегии
protocol SortStrategy {
    func sort<T: Comparable>(_ array: [T]) -> [T]
}

// 2. Конкретные стратегии
class BubbleSortStrategy: SortStrategy {
    func sort<T: Comparable>(_ array: [T]) -> [T] {
        var result = array
        for i in 0..<result.count {
            for j in 1..<result.count - i {
                if result[j] < result[j-1] {
                    result.swapAt(j, j-1)
                }
            }
        }
        return result
    }
}

class QuickSortStrategy: SortStrategy {
    func sort<T: Comparable>(_ array: [T]) -> [T] {
        guard array.count > 1 else { return array }
        let pivot = array[array.count/2]
        let less = array.filter { $0 < pivot }
        let equal = array.filter { $0 == pivot }
        let greater = array.filter { $0 > pivot }
        return sort(less) + equal + sort(greater)
    }
}

// 3. Контекст, использующий стратегию
class Sorter {
    private var strategy: SortStrategy

    init(strategy: SortStrategy) {
        self.strategy = strategy
    }

    func setStrategy(_ strategy: SortStrategy) {
        self.strategy = strategy
    }

    func performSort<T: Comparable>(on array: [T]) -> [T] {
        return strategy.sort(array)
    }
}

// 4. Использование
let numbers = [64, 34, 25, 12, 22, 11, 90]

let sorter = Sorter(strategy: BubbleSortStrategy())
print(sorter.performSort(on: numbers)) // [11, 12, 22, 25, 34, 64, 90]

// Динамическая смена алгоритма
sorter.setStrategy(QuickSortStrategy())
print(sorter.performSort(on: numbers)) // [11, 12, 22, 25, 34, 64, 90]

Другие примеры использования:

  • Расчёт стоимости доставки (Standard, Express, International).
  • Способы оплаты (CreditCard, PayPal, ApplePay).
  • Алгоритмы сжатия (ZIP, RAR, 7z).

Преимущества:

  • Избегание условных операторов.
  • Принцип открытости/закрытости: Легко добавлять новые стратегии.
  • Выбор алгоритма во время выполнения.
  • Изоляция кода и данных алгоритмов от контекста.