Gymterview
junior

Что такое паттерн Strategy?

Strategy – паттерн, определяющий семейство алгоритмов, инкапсулирующий каждый и делающий их взаимозаменяемыми. Клиент выбирает алгоритм в runtime.

Аналогия из жизни: Strategy – как навигатор с выбором маршрута. Вы можете ехать “быстрее”, “короче” или “без платных дорог” – алгоритм маршрутизации меняется, а интерфейс навигатора остаётся прежним.

Strategy через интерфейс
// Интерфейс стратегии
interface PricingStrategy {
    BigDecimal calculatePrice(BigDecimal basePrice, int quantity);
}

// Конкретные стратегии
class RegularPricing implements PricingStrategy {
    public BigDecimal calculatePrice(BigDecimal basePrice, int quantity) {
        return basePrice.multiply(BigDecimal.valueOf(quantity));
    }
}

class BulkPricing implements PricingStrategy {
    public BigDecimal calculatePrice(BigDecimal basePrice, int quantity) {
        BigDecimal discount = quantity > 100 ? new BigDecimal("0.8") : new BigDecimal("0.9");
        return basePrice.multiply(BigDecimal.valueOf(quantity)).multiply(discount);
    }
}

// Контекст, использующий стратегию
class OrderService {
    private final PricingStrategy pricingStrategy;

    OrderService(PricingStrategy pricingStrategy) { // внедряется через DI
        this.pricingStrategy = pricingStrategy;
    }

    BigDecimal calculateTotal(BigDecimal price, int qty) {
        return pricingStrategy.calculatePrice(price, qty);
    }
}

С лямбдами (Java 8+) Strategy можно реализовать без отдельных классов:

Пример
Map<String, BiFunction<BigDecimal, Integer, BigDecimal>> strategies = Map.of(
    "regular", (price, qty) -> price.multiply(BigDecimal.valueOf(qty)),
    "bulk",    (price, qty) -> price.multiply(BigDecimal.valueOf(qty))
                                    .multiply(new BigDecimal("0.85"))
);

BigDecimal total = strategies.get("bulk").apply(price, quantity);

Важное

  • Strategy = OCP (Open/Closed Principle) на практике
  • В Java 8+ простые Strategy заменяются лямбдами (Comparator, Function)
  • Spring: стратегии как бины, выбор через @Qualifier или Map<String, Strategy>

Частые ошибки

  • Strategy + if/else для выбора – выбор стратегии через DI/Map, а не через if/else
  • Strategy для двух строк кода – лямбда проще отдельного класса

Как используется в 2026

  • Comparator, Predicate, Function – встроенные Strategy в JDK
  • Spring: List<PaymentStrategy> – Spring автоматически собирает все реализации

На собеседовании: покажите связь Strategy с OCP и объясните, когда достаточно лямбды вместо полноценного класса. Частая ошибка – реализовать Strategy, а выбор стратегии сделать через if/else, что сводит весь паттерн на нет.