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

Ответ

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).

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

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

Ответ 18+ 🔞

А, паттерн «Стратегия»! Ну это ж классика, блядь, как «Муму» у Тургенева, только без утопления собак, а с утоплением в условных операторах!

Смотри, в чём суть трагедии. Есть у тебя класс, а в нём, сука, сидит такой здоровый Герасим-метод, который внутри себя делает выбор: «Если так — делай раз, если эдак — делай два». И этих «если» там, блядь, овердохуища! Получается пиздопроебибна из switch-case и if-else, которая раздувается, как жопа у ткачихи из сказки. Добавить новый алгоритм? Да это ж переписать полкласса, в рот меня чих-пых!

И тут приходит стратегия, как добрая фея, и говорит: «А давайте, блядь, вынесем каждый этот поганый алгоритм в отдельный домик-класс!». И делает их взаимозаменяемыми, как носки, ёпта.

Смотри, как это на 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)) // Результат тот же, но внутри — другой мир!

Вот и вся философия, блядь. Вместо того чтобы пихать в один метод кучу if (type == "bubble"), ты просто подсовываешь контексту нужную стратегию. Хочешь посчитать доставку? StandardShipping, ExpressShipping, InternationalShipping — нате вам, хуй с горы, выбирайте. Способы оплаты? Да похуй! CreditCardStrategy, PayPalStrategy, CryptoStrategy — подставляй и не парься.

Преимущества? Да их, блядь, как собак нерезаных:

  • Условных операторов — ноль ебать. Никаких монструозных switch-case.
  • Принцип «открыт-закрыт» в действии. Новый алгоритм? Просто новый класс стратегии, и в пизду, ни одну строчку в старом коде не тронул.
  • Меняй алгоритмы как перчатки, прямо во время выполнения. Гибкость — пиздец.
  • Всё изолировано. Каждая стратегия живёт в своём домике и не срёт в общий коридор.

Короче, стратегия — это когда ты перестаёшь быть тем самым мудаком, который пихает всю логику в один метод, и начинаешь мыслить архитектурно. Почти как Тургенев, только про код.