Перейти к содержанию

Strategy.cs

Код подключён напрямую из исходного файла в кодировке UTF-8, поэтому эта страница всегда показывает его актуальную версию.

← К конспекту Скачать исходный файл

Strategy.cs
using System;
using System.Collections.Generic;
using System.Linq;

namespace DesignPatterns.Behavioral.Strategy
{
    // Вариант 1: классическая реализация через интерфейс.
    // Уместна, когда у алгоритма несколько операций или своё внутреннее состояние.
    public interface IDiscountStrategy
    {
        decimal Apply(decimal totalPrice);
    }

    public sealed class NoDiscount : IDiscountStrategy
    {
        public decimal Apply(decimal totalPrice) => totalPrice;
    }

    public sealed class PercentageDiscount : IDiscountStrategy
    {
        private readonly decimal _percent;

        public PercentageDiscount(decimal percent) => _percent = percent;

        public decimal Apply(decimal totalPrice) => totalPrice * (1 - _percent / 100m);
    }

    public sealed class FixedAmountDiscount : IDiscountStrategy
    {
        private readonly decimal _amount;

        public FixedAmountDiscount(decimal amount) => _amount = amount;

        public decimal Apply(decimal totalPrice) => Math.Max(0, totalPrice - _amount);
    }

    // Контекст, использующий стратегию. Он не знает, какая конкретно скидка применяется -
    // это решает вызывающий код, подставляя нужную реализацию.
    public sealed class Order
    {
        private readonly IDiscountStrategy _discountStrategy;
        private readonly decimal _totalPrice;

        public Order(decimal totalPrice, IDiscountStrategy discountStrategy)
        {
            _totalPrice = totalPrice;
            _discountStrategy = discountStrategy;
        }

        public decimal GetFinalPrice() => _discountStrategy.Apply(_totalPrice);
    }

    // Вариант 2: стратегия как делегат - когда алгоритм это одна операция без состояния,
    // в C# зачастую нет смысла заводить под неё интерфейс и класс.
    public static class SortingDemo
    {
        public static IEnumerable<T> SortBy<T>(IEnumerable<T> items, Comparison<T> strategy)
        {
            var list = items.ToList();
            list.Sort(strategy);
            return list;
        }
    }

    public static class Demo
    {
        public static void Run()
        {
            var order1 = new Order(1000m, new PercentageDiscount(10));
            var order2 = new Order(1000m, new FixedAmountDiscount(150));

            Console.WriteLine($"Со скидкой 10%: {order1.GetFinalPrice():C}");
            Console.WriteLine($"Со скидкой 150: {order2.GetFinalPrice():C}");

            // Здесь стратегия сортировки передаётся просто как лямбда (делегат),
            // без отдельного интерфейса ISortStrategy.
            var names = new[] { "Борис", "Анна", "Вера" };
            var sorted = SortingDemo.SortBy(names, (a, b) => string.CompareOrdinal(a, b));
            Console.WriteLine(string.Join(", ", sorted));
        }
    }
}