Шаблон проектирования - Strategy в Java
- Шаблон проектирования Strategy
- Преймущества
- Пример применения
- Вывод
Содержание
Шаблон проектирования Strategy.
Шаблон проектирования
Strategy
— это поведенческий шаблон, который позволяет определить семейство алгоритмов, инкапсулировать каждый из них в виде объекта и сделать их взаимозаменяемыми. Этот шаблон позволяет изменять алгоритмы независимо от клиентов, которые их используют, что упрощает добавление, изменение или удаление алгоритмов, не затрагивая клиентов.
Шаблон Strategy
состоит из трех основных компонентов: контекста, интерфейса стратегии и конкретных стратегий.
-
Контекст: Контекст определяет интересующий клиентов интерфейс и поддерживает ссылку на объект стратегии. Он делегирует работу объекту стратегии, а также может изменять его состояние на основе результатов.
-
Интерфейс
Strategy
: Интерфейс стратегии определяет общий интерфейс для всех конкретных стратегий. Обычно он объявляет один или несколько методов, которые контекст может использовать для вызова алгоритма стратегии. -
Реализация
Strategy
: Конкретные стратегии реализуют интерфейс стратегии и предоставляют различные реализации алгоритма стратегии.
Шаблон Strategy
работает, позволяя контексту динамически выбирать конкретную стратегию из семейства алгоритмов во время выполнения, в зависимости от потребностей приложения. Это позволяет легко переключаться между различными алгоритмами или добавлять новые без изменения контекста или кода клиента.
Шаблон стратегии предлагает несколько преимуществ:
-
Разделение ответственности: шаблон
Strategy
отделяет реализацию алгоритма от клиентского кода, упрощая поддержку и модификацию кода. -
Гибкость. Шаблон
Strategy
позволяет добавлять, удалять или изменять алгоритмы во время выполнения, не затрагивая клиентский код. -
Повторное использование: шаблон
Strategy
позволяет повторно использовать алгоритмы в разных контекстах, уменьшая дублирование кода. -
Тестируемость: шаблон
Strategy
упрощает тестирование реализации алгоритма независимо от клиентского кода, повышая тестируемость и снижая риск ошибок.
Рассмотрим пример того, как вы можете использовать шаблон стратегии и шаблон фабрики в Spring Boot для реализации службы обмена валюты. Допустим, у вас есть веб-сервис электронной коммерции, который позволяет клиентам конвертировать валюту. Чтобы реализовать это, вам нужно иметь способ конвертировать валюту в валюту по выбору клиента. Спроектируем модель данных - валюта:
public enum Currency {
USD, EURO
}
Дальше необходимо определить интерфейс сервиса обмена валюты:
public interface CurrencyExchangeService {
BigDecimal exchange(BigDecimal amount);
Currency getSourceCurrency();
Currency getTargetCurrency();
}
Этот интерфейс определяет метод обмена заданного количества валюты с одной валюты на другую, а также методы получения исходной и целевой валют.
Далее определим фабрику для создания сервисов обмена валюты на основе исходной и целевой валюты:
@Component
public class CurrencyExchangeServiceFactory {
private final Map<CurrencyKey, CurrencyExchangeService> serviceMap = new HashMap<>();
public CurrencyExchangeServiceFactory(@NonNull final List<CurrencyExchangeService> services) {
services.forEach(service -> {
CurrencyKey currencies = new CurrencyKey(service.getSourceCurrency(), service.getTargetCurrency());
serviceMap.put(currencies, service);
});
}
public CurrencyExchangeService getCurrencyExchangeService(@NonNull final Currency sourceCurrency, @NonNull final Currency targetCurrency) {
return serviceMap.get(new CurrencyKey(sourceCurrency, targetCurrency));
}
}
где CurrencyKey:
public record CurrencyKey(Currency from, Currency to) {
}
Эта фабрика берет список служб обмена валюты и создает карту экземпляров служб на основе исходной и целевой валют. Метод getCurrencyExchangeService
возвращает экземпляр службы на основе исходной и целевой валют.
Теперь давайте определим некоторые услуги по обмену валюты, используя шаблон стратегии: Пример стратегии конвертации из евро в доллары
@Component
public class EurToUsdCurrencyExchangeService implements CurrencyExchangeService {
private final BigDecimal exchangeRate = BigDecimal.valueOf(1.20);
@Override
public BigDecimal exchange(@NonNull final BigDecimal amount) {
return amount.multiply(exchangeRate);
}
@Override
public Currency getSourceCurrency() {
return EURO;
}
@Override
public Currency getTargetCurrency() {
return USD;
}
}
Пример стратегии конвертации долларов в евро
@Component
public class UsdToEurCurrencyExchangeService implements CurrencyExchangeService {
private final BigDecimal exchangeRate = BigDecimal.valueOf(0.84);
@Override
public BigDecimal exchange(@NonNull final BigDecimal amount) {
return amount.multiply(exchangeRate);
}
@Override
public Currency getSourceCurrency() {
return USD;
}
@Override
public Currency getTargetCurrency() {
return EURO;
}
}
Эти сервисы реализуют CurrencyExchangeService
интерфейс и предоставляют исходную и целевую валюты, с которыми они работают. Метод exchange
содержит алгоритм обмена валют.
Наконец, давайте используем фабрику для обмена валют:
public interface CurrencyExchanger {
BigDecimal exchange(BigDecimal amount, Currency sourceCurrency, Currency targetCurrency);
}
@Service
@RequiredArgsConstructor
public class CurrencyExchangerImpl implements CurrencyExchanger {
private final CurrencyExchangeServiceFactory factory;
@Override
public BigDecimal exchange(@NonNull final BigDecimal amount, @NonNull final Currency sourceCurrency, @NonNull final Currency targetCurrency) {
CurrencyExchangeService service = factory.getCurrencyExchangeService(sourceCurrency, targetCurrency);
return service.exchange(amount);
}
}
Этот сервис использует фабрику, чтобы получить соответствующую услугу обмена валюты на основе исходной и целевой валют. Затем он вызывает exchange
метод экземпляра службы для обмена валют.
Теперь пришло время реализовать веб-сервис по конвертации валют:
@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
public class ExchangerController {
private final CurrencyExchanger currencyExchanger;
@GetMapping("/exchange")
public ResponseEntity<BigDecimal> exchange(@RequestParam final int value, @RequestParam final Currency from, @RequestParam final Currency to) {
return ResponseEntity.ok(currencyExchanger.exchange(BigDecimal.valueOf(value), from, to));
}
}
Проверить работоспособность можно так - http://localhost:8080/api/exchange?value=100&from=EURO&to=USD
В целом, шаблон стратегии с Spring — это мощный инструмент, который позволяет вам управлять несколькими алгоритмами или стратегиями в вашем приложении. Это повышает гибкость вашего кода, уменьшая дублирование кода и способствуя повторному использованию кода.