Приведи пример использования паттерна Strategy
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Пример использования паттерна Strategy
Паттерн Strategy (Стратегия) — это поведенческий паттерн проектирования, который определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми. Это позволяет изменять алгоритмы независимо от клиентов, которые ими пользуются. Основная идея — вынести изменяющуюся часть алгоритма в отдельные классы-стратегии, чтобы основной класс (контекст) мог делегировать выполнение этому объекту. Это соответствует принципу Open/Closed Principle (принцип открытости/закрытости) — класс открыт для расширения, но закрыт для модификации.
Классический пример: система оплаты в приложении
Рассмотрим сценарий Android-приложения для электронной коммерции, где пользователь может выбрать различные способы оплаты — кредитная карта, PayPal, Google Pay. Вместо реализации условных операторов (if/else или switch) внутри класса заказа, мы выделяем стратегии оплаты.
1. Определяем интерфейс стратегии
Создадим интерфейс PaymentStrategy, который объявляет метод для выполнения оплаты.
interface PaymentStrategy {
fun pay(amount: Double): Boolean
}
2. Реализуем конкретные стратегии
Каждый способ оплаты реализует этот интерфейс по-своему.
class CreditCardStrategy(
private val cardNumber: String,
private val cvv: String
) : PaymentStrategy {
override fun pay(amount: Double): Boolean {
// Логика оплаты через кредитную карту (например, интеграция с платежным шлюзом)
println("Оплата $amount через кредитную карту $cardNumber")
return true // В реальности здесь была бы проверка успешности транзакции
}
}
class PayPalStrategy(
private val email: String
) : PaymentStrategy {
override fun pay(amount: Double): Boolean {
// Логика оплаты через PayPal
println("Оплата $amount через PayPal аккаунт $email")
return true
}
}
class GooglePayStrategy : PaymentStrategy {
override fun pay(amount: Double): Boolean {
// Логика оплаты через Google Pay
println("Оплата $amount через Google Pay")
return true
}
}
3. Создаем контекст (класс, использующий стратегию)
Класс ShoppingCart будет делегировать оплату выбранной стратегии.
class ShoppingCart(private var paymentStrategy: PaymentStrategy) {
private val items = mutableListOf<Pair<String, Double>>()
fun addItem(name: String, price: Double) {
items.add(name to price)
}
fun calculateTotal(): Double {
return items.sumOf { it.second }
}
fun setPaymentStrategy(strategy: PaymentStrategy) {
this.paymentStrategy = strategy
}
fun checkout(): Boolean {
val total = calculateTotal()
if (total > 0) {
return paymentStrategy.pay(total)
}
return false
}
}
4. Использование в Android-приложении
Например, в Activity или ViewModel мы можем динамически менять стратегию оплаты в зависимости от выбора пользователя.
class CheckoutActivity : AppCompatActivity() {
private lateinit var cart: ShoppingCart
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_checkout)
// Инициализация корзины с дефолтной стратегией (например, Google Pay)
cart = ShoppingCart(GooglePayStrategy())
cart.addItem("Android Book", 29.99)
cart.addItem("USB-C Cable", 12.50)
// Обработчики выбора оплаты
creditCardButton.setOnClickListener {
val cardStrategy = CreditCardStrategy("1234-5678-9012-3456", "123")
cart.setPaymentStrategy(cardStrategy)
proceedToPay()
}
paypalButton.setOnClickListener {
val paypalStrategy = PayPalStrategy("user@example.com")
cart.setPaymentStrategy(paypalStrategy)
proceedToPay()
}
}
private fun proceedToPay() {
val success = cart.checkout()
if (success) {
showSuccessMessage()
} else {
showErrorMessage()
}
}
}
Преимущества использования Strategy в Android-разработке:
- Гибкость и расширяемость: Добавление нового способа оплаты (например, Apple Pay или криптовалюта) требует только создания нового класса, реализующего
PaymentStrategy, без изменения существующего кода корзины или UI. - Упрощение тестирования: Каждую стратегию можно тестировать изолированно с помощью Unit-тестов (например, используя JUnit и Mockito).
- Соблюдение принципов SOLID:
- Single Responsibility: Каждая стратегия отвечает только за свой алгоритм оплаты.
- Open/Closed: Класс
ShoppingCartзакрыт для модификации, но открыт для расширения через новые стратегии. - Dependency Inversion: Контекст зависит от абстракции (
PaymentStrategy), а не от конкретных реализаций.
- Упрощение UI-логики: В
Activity/Fragmentне нужно плодить сложные условия, что улучшает читаемость и поддержку кода.
Другие сценарии использования в Android:
- Стратегии кэширования: Выбор между кэшем в памяти, на диске или сетевым запросом.
- Стратегии сортировки/фильтрации: Разные алгоритмы для списков товаров.
- Стратегии анимации: Разные типы анимаций переходов между экранами.
- Стратегии логирования: Выбор вывода в Logcat, файл или отправку на сервер.
Таким образом, паттерн Strategy помогает создавать гибкую и поддерживаемую архитектуру, что критически важно для долгосрочной разработки сложных Android-приложений. Он особенно полезен при работе с часто изменяющимися бизнес-правилами или интеграциями со сторонними сервисами.