Найти тему
🚲Макс💻Код🩼

Разбор паттерна Стратегия

Оглавление

Стратегия предоставляет механизм, позволяющий менять алгоритмы поведения объектов на лету. Он особенно полезен для реализации гибких систем, где необходимо часто менять логику работы. Относится к поведенческим паттернам проектирования и позволяет определять семейство алгоритмов, инкапсулировать каждый из них и делать их взаимозаменяемыми. Это способствует разделению алгоритма и его использования, что повышает гибкость и расширяемость кода.

Предположим, у нас есть система, обрабатывающая платежи, и нам нужно поддерживать различные методы оплаты (кредитные карты, PayPal, криптовалюты и т.д.). Без использования "Стратегии" наш код может выглядеть следующим образом:

public class PaymentService {
public void processPayment(String paymentType) {
if (paymentType.equals("credit_card")) {
// Логика обработки кредитной карты
} else if (paymentType.equals("paypal")) {
// Логика обработки PayPal
} else if (paymentType.equals("crypto")) {
// Логика обработки криптовалюты
}
}
}

Использование паттерна "Стратегия" позволяет избежать длинных цепочек условных операторов и сделать код более модульным и расширяемым. Мы создадим общий интерфейс для всех стратегий оплаты и реализуем конкретные стратегии.

Определение Интерфейса Стратегии

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

Реализация Конкретных Стратегий

@Component
public class CreditCardPayment implements PaymentStrategy {
@Override
public void pay(double amount) {
// Логика обработки кредитной карты
System.out.println("Paid " + amount + " using Credit Card.");
}
}

@Component
public class PayPalPayment implements PaymentStrategy {
@Override
public void pay(double amount) {
// Логика обработки PayPal
System.out.println("Paid " + amount + " using PayPal.");
}
}

@Component
public class CryptoPayment implements PaymentStrategy {
@Override
public void pay(double amount) {
// Логика обработки криптовалюты
System.out.println("Paid " + amount + " using Crypto.");
}
}

Контекст Использования Стратегии

Теперь мы создадим класс PaymentService, который будет использовать различные стратегии оплаты.

@Component
public class PaymentService {
private final Map<String, PaymentStrategy> strategies;
@Autowired
public PaymentService(List<PaymentStrategy> strategiesList) {
strategies = strategiesList.stream()
.collect(Collectors.toMap(
strategy -> strategy.getClass().getSimpleName().replace("Payment", "").toLowerCase(),
strategy -> strategy
));
}
public void processPayment(String paymentType, double amount) {
PaymentStrategy strategy = strategies.get(paymentType.toLowerCase());
if (strategy != null) {
strategy.pay(amount);
} else {
throw new IllegalArgumentException("Payment type " + paymentType + " not supported.");
}
}
}

Пример использования:

@SpringBootApplication
public class StrategyPatternExample {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(StrategyPatternExample.class, args);
PaymentService paymentService = context.getBean(PaymentService.class);
paymentService.processPayment("creditcard", 100.0);
paymentService.processPayment("paypal", 200.0);
paymentService.processPayment("crypto", 300.0);
}
}

Преимущества

1. Расширяемость: Легко добавлять новые стратегии без изменения существующего кода.

2. Снижение Связанности: Клиенты (например, PaymentService) не зависят от конкретных реализаций стратегий.

3. Упрощение Кода: Избавляемся от громоздких условных операторов и делаем код более читаемым.

Заключение

Паттерн "Стратегия" предоставляет мощное средство для управления алгоритмами и их поведения в приложениях. Используя Spring, мы можем легко внедрять и управлять стратегиями через аннотации и классы конфигурации, что делает наш код более гибким и поддерживаемым. Этот паттерн идеально подходит для ситуаций, когда вам нужно динамически менять поведение вашего приложения в зависимости от конкретных условий.