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

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

2.2 Middle🔥 161 комментариев
#ООП и паттерны проектирования

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

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

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

Пример реализации паттерна Strategy в C#

Паттерн Strategy (Стратегия) — это поведенческий паттерн проектирования, который определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми. Он позволяет изменять алгоритмы независимо от клиентов, которые их используют.

Ключевые компоненты паттерна:

  • Контекст (Context): Класс, который использует стратегию. Он хранит ссылку на объект стратегии и может её заменять.
  • Интерфейс стратегии (IStrategy): Общий интерфейс для всех конкретных стратегий.
  • Конкретные стратегии (ConcreteStrategy): Классы, реализующие интерфейс стратегии, каждый — свою версию алгоритма.

Практический пример: Система оплаты в интернет-магазине

Рассмотрим реализацию системы обработки платежей, где пользователь может выбрать разные способы оплаты.

1. Определяем интерфейс стратегии

// Интерфейс стратегии
public interface IPaymentStrategy
{
    bool ProcessPayment(decimal amount);
    string GetPaymentMethodName();
}

2. Реализуем конкретные стратегии

// Конкретная стратегия: Оплата кредитной картой
public class CreditCardPaymentStrategy : IPaymentStrategy
{
    private readonly string _cardNumber;
    private readonly string _cvv;

    public CreditCardPaymentStrategy(string cardNumber, string cvv)
    {
        _cardNumber = cardNumber;
        _cvv = cvv;
    }

    public bool ProcessPayment(decimal amount)
    {
        // Логика обработки платежа через кредитную карту
        Console.WriteLine($"Обработка платежа {amount} руб. через кредитную карту {_cardNumber[^4..]}");
        
        // Имитация проверки
        return !string.IsNullOrEmpty(_cardNumber) && _cardNumber.Length ==706;
    }

    public string GetPaymentMethodName() => "Кредитная карта";
}

// Конкретная стратегия: Оплата через PayPal
public class PayPalPaymentStrategy : IPaymentStrategy
{
    private readonly string _email;

    public PayPalPaymentStrategy(string email)
    {
        _email = email;
    }

    public bool ProcessPayment(decimal amount)
    {
        // Логика обработки платежа через PayPal
        Console.WriteLine($"Обработка платежа {amount} руб. через PayPal аккаунт {_email}");
        
        // Имитация проверки
        return _email.Contains("@");
    }

    public string GetPaymentMethodName() => "PayPal";
}

// Конкретная стратегия: Оплата криптовалютой
public class CryptoPaymentStrategy : IPaymentStrategy
{
    private readonly string _walletAddress;

    public CryptoPaymentStrategy(string walletAddress)
    {
        _walletAddress = walletAddress;
    }

    public bool ProcessPayment(decimal amount)
    {
        // Логика обработки платежа криптовалютой
        Console.WriteLine($"Обработка платежа {amount} руб. через криптокошелёк {_walletAddress[..10]}...");
        
        // Имитация проверки
        return _walletAddress.StartsWith("0x");
    }

    public string GetPaymentMethodName() => "Криптовалюта";
}

3. Создаём контекст

// Контекст: Заказ в интернет-магазине
public class Order
{
    private IPaymentStrategy _paymentStrategy;
    public decimal TotalAmount { get; private set; }
    public bool IsPaid { get; private set; }

    public Order(decimal totalAmount)
    {
        TotalAmount = totalAmount;
        IsPaid = false;
    }

    // Метод для установки стратегии (можно менять на лету)
    public void SetPaymentStrategy(IPaymentStrategy paymentStrategy)
    {
        _paymentStrategy = paymentStrategy;
        Console.WriteLine($"Выбран способ оплаты: {_paymentStrategy.GetPaymentMethodName()}");
    }

    // Метод выполнения оплаты
    public bool ProcessOrderPayment()
    {
        if (_paymentStrategy == null)
        {
            Console.WriteLine("Не выбран способ оплаты!");
            return false;
        }

        Console.WriteLine($"\nОбработка заказа на сумму {TotalAmount} руб.");
        IsPaid = _paymentStrategy.ProcessPayment(TotalAmount);
        
        if (IsPaid)
        {
            Console.WriteLine("✅ Платёж успешно обработан!");
        }
        else
        {
            Console.WriteLine("❌ Ошибка обработки платежа");
        }
        
        return IsPaid;
    }
}

4. Использование паттерна Strategy

class Program
{
    static void Main(string[] args)
    {
        // Создаём заказ
        var order = new Order(9999.99m);
        
        Console.WriteLine("=== Пример 1: Оплата кредитной картой ===");
        order.SetPaymentStrategy(new CreditCardPaymentStrategy("1234567812345678", "123"));
        order.ProcessOrderPayment();
        
        Console.WriteLine("\n=== Пример 2: Оплата PayPal ===");
        order.SetPaymentStrategy(new PayPalPaymentStrategy("customer@example.com"));
        order.ProcessOrderPayment();
        
        Console.WriteLine("\n=== Пример 3: Оплата криптовалютой ===");
        order.SetPaymentStrategy(new CryptoPaymentStrategy("0x71C7656EC7ab88b098defB751B7401B5f6d8976F"));
        order.ProcessOrderPayment();
        
        Console.WriteLine("\n=== Пример 4: Динамическая смена стратегии ===");
        // Пользователь передумал и выбрал другой способ
        order.SetPaymentStrategy(new CreditCardPaymentStrategy("8765432187654321", "456"));
        order.ProcessOrderPayment();
    }
}

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

  • Принцип открытости/закрытости (OCP): Можно добавлять новые стратегии, не изменяя существующий код контекста.
  • Избавление от условных операторов: Заменяет громоздкие switch или if-else конструкции на полиморфизм.
  • Инкапсуляция алгоритмов: Каждая стратегия изолирована в своём классе.
  • Возможность тестирования: Каждую стратегию можно тестировать независимо.
  • Динамическая смена поведения: Стратегию можно менять во время выполнения программы.

Типичные сценарии применения в Backend-разработке

  1. Алгоритмы сортировки и фильтрации данных
  2. Различные способы аутентификации (JWT, OAuth, API-ключи)
  3. Форматирование данных (JSON, XML, CSV)
  4. Стратегии кеширования (MemoryCache, Redis, Database)
  5. Стратегии логирования (File, Database, Cloud)
  6. Расчёт доставки разными транспортными компаниями
  7. Генерация отчётов в разных форматах

Паттерн Strategy особенно полезен в микросервисной архитектуре, где разные сервисы могут требовать различных алгоритмов обработки данных, и необходимо обеспечить гибкость и лёгкость расширения системы.

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