PatternsCSharpExtraAddons/Patterns/Pattern_1-Стратегия/Program.cs

158 lines
5.6 KiB
C#
Raw Permalink Normal View History

2024-10-05 09:30:14 +03:00
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}");
}
}
/// <summary>
/// Реализует интерфейс сортировки
/// Добавлет возможность сортировки по ID по возрастающей
/// </summary>
class EmployeeByIdComparer : IComparer<Employee>
{
int IComparer<Employee>.Compare(Employee? x, Employee? y)
{
if(x is Employee xx && y is Employee yy)
return xx.Id.CompareTo(yy.Id);
else
return 0;
}
}
/// <summary>
/// Фабричный класс для создания экземпляров IComparer
/// </summary>
class ComparerFactory
{
public static IComparer<T> Create<T>(Comparison<T> comparer)
{
return new DelegateComparer<T>(comparer);
}
private class DelegateComparer<T> : IComparer<T>
{
private readonly Comparison<T> _comparer;
public DelegateComparer(Comparison<T> 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<Employee> list)
{
list.Sort(new EmployeeByIdComparer()); //используем функтор
}
public static void SortListName(List<Employee> list)
{
list.Sort((x, y) => x.Name.CompareTo(y.Name)); //используем делегат
}
static void Main(string[] args)
{
var logFileReader = new LogFileReader();
/*
создали делегат который принимает в себя метод,
в результате выполнения которого возвращается List<LogEntry>
*/
Func<List<LogEntry>> _import = () => logFileReader.Read();
new LogProcessor(_import).ProcessLogs();
var employees = new List<Employee>
{
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<Employee>(comparer);
/*
конструктор принимает IComparable
нет конструктора, принимающего делегат Comparison<T>
можно создать небольшой адаптерный фабричный класс
*/
var comparer_factory = ComparerFactory.Create<Employee>((x, y) => x.Id.CompareTo(y.Id));
var set_factory = new SortedSet<Employee>(comparer_factory); //он помещает сюда фабрику - ту что умеет создавать
}
}