Ответ
Паттерн Стратегия (Strategy) — это поведенческий паттерн, который определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми. Он позволяет изменять алгоритм независимо от клиента, который его использует.
Реализация на Java
-
Интерфейс стратегии: Определяет общий метод для всех алгоритмов.
public interface PaymentStrategy { void pay(int amount); } -
Конкретные стратегии: Реализуют различные алгоритмы.
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; // Очистка корзины после оплаты
}
}
-
Использование клиентом:
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, сука
-
Интерфейс-договорённость. Все наши алгоритмы должны уметь делать одно и то же. Например, платить.
public interface PaymentStrategy { void pay(int amount); }Всё, больше нихуя. Просто метод
pay. -
Конкретные бандиты. Это и есть наши стратегии. Каждая делает одно и то же, но по-своему, как последняя мразота.
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; // Корзину очистили
}
}
-
А теперь используем это всё, как бог черепаху.
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") {...}. Чистый полиморфизм, мать его. - Всё по полочкам. Каждый алгоритм сидит в своём классе. Тестировать — одно удовольствие. Понять, где что сломалось — тоже. Не эта пиздопроебищная куча кода в одном методе.
В общем, если у тебя есть что-то, что делается разными способами, и эти способы могут меняться или добавляться — это прям крик души паттерна Стратегия. Используй, не ёбись.