Стратегия предоставляет механизм, позволяющий менять алгоритмы поведения объектов на лету. Он особенно полезен для реализации гибких систем, где необходимо часто менять логику работы. Относится к поведенческим паттернам проектирования и позволяет определять семейство алгоритмов, инкапсулировать каждый из них и делать их взаимозаменяемыми. Это способствует разделению алгоритма и его использования, что повышает гибкость и расширяемость кода.
Предположим, у нас есть система, обрабатывающая платежи, и нам нужно поддерживать различные методы оплаты (кредитные карты, 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, мы можем легко внедрять и управлять стратегиями через аннотации и классы конфигурации, что делает наш код более гибким и поддерживаемым. Этот паттерн идеально подходит для ситуаций, когда вам нужно динамически менять поведение вашего приложения в зависимости от конкретных условий.