Приведи пример поведенческого паттерна проектирования.

Ответ

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

Реализация на Java

  1. Интерфейс стратегии: Определяет общий метод для всех алгоритмов.

    public interface PaymentStrategy {
    void pay(int amount);
    }
  2. Конкретные стратегии: Реализуют различные алгоритмы.

    
    public class CreditCardPayment implements PaymentStrategy {
    private String cardNumber;
    private String cvv;
    
    public CreditCardPayment(String cardNumber, String cvv) {
        this.cardNumber = cardNumber;
        this.cvv = cvv;
    }
    
    @Override
    public void pay(int amount) {
        System.out.println("Paid " + amount + " using Credit Card (" + cardNumber.substring(12) + ")");
        // Логика взаимодействия с платежным шлюзом для карты
    }
    }

public 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 (" + email + ")");
    // Логика взаимодействия с API PayPal
}

}

public class CryptoPayment implements PaymentStrategy { private String walletAddress;

public CryptoPayment(String walletAddress) {
    this.walletAddress = walletAddress;
}

@Override
public void pay(int amount) {
    System.out.println("Paid " + amount + " using Crypto to address: " + walletAddress.substring(0, 8) + "...");
    // Логика проведения крипто-транзакции
}

}


3.  **Контекст:** Хранит ссылку на стратегию и делегирует ей работу.
```java
public class ShoppingCart {
    private PaymentStrategy paymentStrategy;
    private int totalAmount = 0;

    public void addItem(int price) {
        totalAmount += price;
    }

    // Метод для динамической смены стратегии
    public void setPaymentStrategy(PaymentStrategy strategy) {
        this.paymentStrategy = strategy;
    }

    public void checkout() {
        if (paymentStrategy == null) {
            throw new IllegalStateException("Payment strategy not set.");
        }
        paymentStrategy.pay(totalAmount); // Делегирование операции стратегии
        totalAmount = 0; // Очистка корзины после оплаты
    }
}
  1. Использование клиентом:

    public class Client {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();
        cart.addItem(100);
        cart.addItem(50);
    
        // Выбор и применение разных стратегий
        cart.setPaymentStrategy(new CreditCardPayment("1234-5678-9012-3456", "123"));
        cart.checkout(); // Вывод: Paid 150 using Credit Card (3456)
    
        cart.addItem(75);
        cart.setPaymentStrategy(new PayPalPayment("user@example.com"));
        cart.checkout(); // Вывод: Paid 75 using PayPal (user@example.com)
    
        cart.addItem(200);
        cart.setPaymentStrategy(new CryptoPayment("0xAbCdEf1234567890"));
        cart.checkout(); // Вывод: Paid 200 using Crypto to address: 0xAbCdEf...
    }
    }

Преимущества паттерна Стратегия:

  • Соблюдение OCP (Open/Closed Principle): Легко добавить новую стратегию, не изменяя существующий код контекста.
  • Устранение условных операторов: Заменяет длинные if-else или switch конструкции на полиморфизм.
  • Изоляция логики алгоритма: Каждый алгоритм находится в своем собственном классе, что упрощает тестирование и понимание.

Ответ 18+ 🔞

Смотри, вот есть у тебя задача, а решить её можно дохуя разными способами. И ты сидишь такой, пишешь эти бесконечные if-else, как последний мудак, а потом начальник приходит и говорит: «А давай-ка ещё вот этот способ оплаты добавь, криптой там какой-нибудь». И ты понимаешь, что твой код уже похож на швейцарский сыр, только дыры — это баги. Вот тут-то и выручает Стратегия, ёпта!

Смысл в чём, блядь? Мы выносим каждый способ решения (каждый алгоритм) в отдельный класс. А наш главный класс (контекст) просто тыкает в него пальцем и говорит: «Работай!». И если завтра надо будет добавить оплату кривыми ракушками — мы просто создадим новый класс, не ковыряясь в старом коде. Красота, блядь!

Как это выглядит на Java, сука

  1. Интерфейс-договорённость. Все наши алгоритмы должны уметь делать одно и то же. Например, платить.

    public interface PaymentStrategy {
    void pay(int amount);
    }

    Всё, больше нихуя. Просто метод pay.

  2. Конкретные бандиты. Это и есть наши стратегии. Каждая делает одно и то же, но по-своему, как последняя мразота.

    
    public class CreditCardPayment implements PaymentStrategy {
    private String cardNumber;
    private String cvv;
    
    public CreditCardPayment(String cardNumber, String cvv) {
        this.cardNumber = cardNumber;
        this.cvv = cvv;
    }
    
    @Override
    public void pay(int amount) {
        System.out.println("Paid " + amount + " using Credit Card (" + cardNumber.substring(12) + ")");
        // Тут была бы логика, которая ебётся с банковским шлюзом
    }
    }

public 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 (" + email + ")");
    // Тут логика, которая ползёт в API PayPal, как таракан
}

}

public class CryptoPayment implements PaymentStrategy { private String walletAddress;

public CryptoPayment(String walletAddress) {
    this.walletAddress = walletAddress;
}

@Override
public void pay(int amount) {
    System.out.println("Paid " + amount + " using Crypto to address: " + walletAddress.substring(0, 8) + "...");
    // А тут магия блокчейна, от которой у нормальных людей ебёт мозг
}

}

Видишь? Каждый класс — отдельная песочница. Один ебётся с картами, другой с PayPal, третий с биткоинами. Они не знают друг о друге, им похуй.

3.  **Контекст — главный по тарелкам.** Это тот, кто всем управляет. У него есть стратегия, и он просто говорит ей: «Сделай дело!».
```java
public class ShoppingCart {
    private PaymentStrategy paymentStrategy; // Ссылка на стратегию
    private int totalAmount = 0;

    public void addItem(int price) {
        totalAmount += price;
    }

    // Вот этот метод — вся соль! Меняем стратегию на лету, как перчатки.
    public void setPaymentStrategy(PaymentStrategy strategy) {
        this.paymentStrategy = strategy;
    }

    public void checkout() {
        if (paymentStrategy == null) {
            throw new IllegalStateException("Payment strategy not set."); // Чувак, ты вообще стратегию выбрал?
        }
        paymentStrategy.pay(totalAmount); // Всё, делегировали работу. Сам контекст нихуя не делает.
        totalAmount = 0; // Корзину очистили
    }
}
  1. А теперь используем это всё, как бог черепаху.

    public class Client {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();
        cart.addItem(100);
        cart.addItem(50);
    
        // Хочу платить картой — хуяк!
        cart.setPaymentStrategy(new CreditCardPayment("1234-5678-9012-3456", "123"));
        cart.checkout(); // Paid 150 using Credit Card (3456)
    
        // Ой, карта не работает, дай PayPal
        cart.addItem(75);
        cart.setPaymentStrategy(new PayPalPayment("user@example.com"));
        cart.checkout(); // Paid 75 using PayPal (user@example.com)
    
        // Во, биткойны подросли, щас покажу всем!
        cart.addItem(200);
        cart.setPaymentStrategy(new CryptoPayment("0xAbCdEf1234567890"));
        cart.checkout(); // Paid 200 using Crypto to address: 0xAbCdEf...
    }
    }

И в чём, блядь, кайф?

  • Принцип открытости/закрытости (OCP) в действии. Хочешь добавить оплату голубиной почтой? Создай класс CarrierPigeonPayment, реализуй интерфейс и подсовывай контексту. Старый код даже не чихнёт.
  • Убили этих ёбаных if-else. Никаких if (paymentType == "card") {...} else if (paymentType == "paypal") {...}. Чистый полиморфизм, мать его.
  • Всё по полочкам. Каждый алгоритм сидит в своём классе. Тестировать — одно удовольствие. Понять, где что сломалось — тоже. Не эта пиздопроебищная куча кода в одном методе.

В общем, если у тебя есть что-то, что делается разными способами, и эти способы могут меняться или добавляться — это прям крик души паттерна Стратегия. Используй, не ёбись.