Ответ
Стратегия (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
}
}
Ключевые преимущества:
- Устранение условных операторов. Поведение инкапсулировано в отдельные классы.
- Динамическая смена алгоритмов. Стратегию можно менять на лету.
- Принцип единственной ответственности. Каждый алгоритм живет в своем классе.
- Упрощение тестирования. Стратегии можно тестировать изолированно.
Типичное применение: системы оплаты, алгоритмы сортировки или сжатия, вариативная логика валидации или расчета доставки.
Ответ 18+ 🔞
А, паттерн Стратегия! Ну это ж классика, блядь, как та самая история про Герасима и Муму, только в мире кода. Слушай, представь себе — ты пишешь код, а там на каждом шагу эти ёбаные if-else или switch, которые раздуваются, как жопа у ткачихи из сказки после пиршества!
Вот в чём суть, ёпта:
У тебя есть какая-то операция — например, оплата. И вариантов её выполнения — дохуя: картой, PayPal, криптой, наличкой, может, даже обещаниями, блядь. И если ты начнёшь всё это впихивать в один метод с ветвлениями, получится пиздопроебина, в которой через месяц сам чёрт ногу сломит.
А паттерн Стратегия говорит: «Да похуй! Выноси каждый алгоритм в отдельный класс, сделай у них общий интерфейс и подсовывай нужный, когда надо». И всё, блядь! Красота!
Смотри, как это выглядит в коде, на примере оплаты:
// 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
// А потом резко передумали — дай PayPal!
cart.setPaymentStrategy(new PayPalPayment("user@example.com"));
cart.checkout(50); // Paid 50 using PayPal account user@example.com
}
}
Видишь? Ни одного if! Никакого «если карта — то так, если PayPal — то эдак». Просто подменил объект — и алгоритм поменялся, как перчатки, блядь. Это и есть динамическая смена стратегии на лету.
Зачем это всё, спросишь?
Да чтобы не превращать код в помойку, где всё завязано на условия! Каждая стратегия живёт в своём классе — её можно тестировать отдельно, расширять, не боясь сломать остальное. Добавил новую платёжку? Создал новый класс, реализовал интерфейс — и вперёд, без правки существующей логики. Это и есть тот самый принцип открытости/закрытости — открыто для расширения, но закрыто для модификации, ёпта!
Где применяется? Да везде, блядь!
— Платёжные системы (как в примере)
— Алгоритмы сортировки или сжатия (выбрал стратегию — получил результат)
— Логика расчёта доставки (почта, курьер, самовывоз)
— Валидация данных (разные правила для разных типов пользователей)
Короче, если видишь, что у тебя в коде расплодились условные ветки на одну и ту же операцию — это верный признак, что пора, сука, внедрять Стратегию. Иначе потом будешь как тот Герасим — молча страдать, глядя на утонувшую в if-else логику.