namespace Behavioral; /* * На чем строилось: * СЕРГЕЙ ТЕПЛЯКОВ - Паттерны проектирования на платформе .Net * ШЕВЧУК, АХРИМЕНКО, КАСЬЯНОВ - Приемы объектно-ориентированного проектирования * * ПАТТЕРНЫ ПОВЕДЕНИЯ * Паттерн_1: Стратегия * * ! является более контекстно зависимой операцией * * Причины применения: * 1.необходимость инкапсуляции поведения или алгоритма * 2.необходимость замены поведения или алгоритма во время исполнения * * Другими словами, стратегия обеспечивает точку расширения системы * в определенной плоскости: класс-контекст (LogProcessor) принимает экземпляр стратегии (LogFileReader) * и не знает, какой вариант стратегии он собирается использовать. * * Особенность: * Передача интерфейса ILogReader классу LogProcessor увеличивает гибкость, * но в то же время повышает сложность. * Теперь клиентам класса LogProcessor нужно решить, какую реализацию использовать, * или переложить эту ответственность на вызывающий код. */ /* * ВМЕСТО * классической стратегии на основе наследования * можно использовать стратегию на основе делегатов * * ПРИМЕР: Стратегия сортировки */ /* * ВАЖНО: Гибкость не бывает бесплатной, поэтому выделять стратегии стоит тогда, * когда действительно нужна замена поведения во время исполнения. */ class Employee { public int Id { get; set; } public string? Name { get; set; } public override string ToString() { return string.Format($"ID={Id}, Name={Name}"); } } /// /// Реализует интерфейс сортировки /// Добавлет возможность сортировки по ID по возрастающей /// class EmployeeByIdComparer : IComparer { int IComparer.Compare(Employee? x, Employee? y) { if(x is Employee xx && y is Employee yy) return xx.Id.CompareTo(yy.Id); else return 0; } } /// /// Фабричный класс для создания экземпляров IComparer /// class ComparerFactory { public static IComparer Create(Comparison comparer) { return new DelegateComparer(comparer); } private class DelegateComparer : IComparer { private readonly Comparison _comparer; public DelegateComparer(Comparison comparer) { _comparer = comparer; } public int Compare(T? x, T? y) { if(x == null || y == null) return 0; return _comparer(x, y); } } } class Program { public static void SortListId(List list) { list.Sort(new EmployeeByIdComparer()); //используем функтор } public static void SortListName(List list) { list.Sort((x, y) => x.Name.CompareTo(y.Name)); //используем делегат } static void Main(string[] args) { var logFileReader = new LogFileReader(); /* создали делегат который принимает в себя метод, в результате выполнения которого возвращается List */ Func> _import = () => logFileReader.Read(); new LogProcessor(_import).ProcessLogs(); var employees = new List { new Employee { Id = 8, Name = "asmus" }, new Employee { Id = 1, Name = "robin" }, new Employee { Id = 2, Name = "satan" }, new Employee { Id = 5, Name = "dastin" } }; SortListId(employees); //отсортировали по id через функтор SortListName(employees); //отсортировали по Name через делегат Console.WriteLine(); var comparer = new EmployeeByIdComparer(); var set = new SortedSet(comparer); /* конструктор принимает IComparable нет конструктора, принимающего делегат Comparison можно создать небольшой адаптерный фабричный класс */ var comparer_factory = ComparerFactory.Create((x, y) => x.Id.CompareTo(y.Id)); var set_factory = new SortedSet(comparer_factory); //он помещает сюда фабрику - ту что умеет создавать } }