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); //он помещает сюда фабрику - ту что умеет создавать
}
}