← Назад к вопросам

Приведи пример использования паттерна Strategy

2.0 Middle🔥 201 комментариев
#Kotlin основы#Архитектура и паттерны

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Пример использования паттерна 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-приложений. Он особенно полезен при работе с часто изменяющимися бизнес-правилами или интеграциями со сторонними сервисами.