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

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

Ответ

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

Зачем он нужен? Чтобы избавиться от громоздких условных операторов (if/else или switch) при выборе поведения и сделать систему гибкой, соответствующей принципу открытости/закрытости (код открыт для расширения, но закрыт для модификации).

Пример на Java (платежная система):

// 1. Общий интерфейс стратегии
interface PaymentStrategy {
    void pay(int amount);
}

// 2. Конкретные стратегии
class CreditCardPayment implements PaymentStrategy {
    private String cardNumber;
    public CreditCardPayment(String cardNumber) { this.cardNumber = cardNumber; }

    @Override
    public void pay(int amount) {
        System.out.println("Paid " + amount + " using Credit Card " + cardNumber.substring(12));
    }
}

class PayPalPayment implements PaymentStrategy {
    private String email;
    public PayPalPayment(String email) { this.email = email; }

    @Override
    public void pay(int amount) {
        System.out.println("Paid " + amount + " using PayPal account " + email);
    }
}

// 3. Контекст, использующий стратегию
class ShoppingCart {
    private PaymentStrategy paymentStrategy;

    public void setPaymentStrategy(PaymentStrategy strategy) {
        this.paymentStrategy = strategy;
    }

    public void checkout(int totalAmount) {
        paymentStrategy.pay(totalAmount);
    }
}

// 4. Использование
public class Main {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();
        cart.setPaymentStrategy(new CreditCardPayment("1234-5678-9012-3456"));
        cart.checkout(100); // Paid 100 using Credit Card 3456

        // Динамическая смена стратегии
        cart.setPaymentStrategy(new PayPalPayment("user@example.com"));
        cart.checkout(50); // Paid 50 using PayPal account user@example.com
    }
}

Ключевые преимущества:

  • Устранение условных операторов. Поведение инкапсулировано в отдельные классы.
  • Динамическая смена алгоритмов. Стратегию можно менять на лету.
  • Принцип единственной ответственности. Каждый алгоритм живет в своем классе.
  • Упрощение тестирования. Стратегии можно тестировать изолированно.

Типичное применение: системы оплаты, алгоритмы сортировки или сжатия, вариативная логика валидации или расчета доставки.