218 lines
7.2 KiB
C#
218 lines
7.2 KiB
C#
/* Стратегия
|
||
Определяет группу алгоритмов,
|
||
инкапсулирует их и делает взаимозаменяемыми.
|
||
Позволяет изменять алгоритм независимо от клиентов,
|
||
его использующих.
|
||
*/
|
||
/*
|
||
* На чем строилось:
|
||
* СЕРГЕЙ ТЕПЛЯКОВ - Паттерны проектирования на платформе .Net
|
||
* ШЕВЧУК, АХРИМЕНКО, КАСЬЯНОВ - Приемы объектно-ориентированного проектирования
|
||
*
|
||
* ПАТТЕРНЫ ПОВЕДЕНИЯ
|
||
* Паттерн №1: Стратегия
|
||
*
|
||
* - является более контекстно зависимой операцией
|
||
*
|
||
* Причины применения:
|
||
* 1.необходимость инкапсуляции поведения или алгоритма
|
||
* 2.необходимость замены поведения или алгоритма во время исполнения
|
||
*
|
||
* Другими словами, стратегия обеспечивает точку расширения системы
|
||
* в определенной плоскости: класс-контекст (LogProcessor) принимает экземпляр стратегии (LogFileReader)
|
||
* и не знает, какой вариант стратегии он собирается использовать.
|
||
*
|
||
* Особенность:
|
||
* Передача интерфейса ILogReader классу LogProcessor увеличивает гибкость,
|
||
* но в то же время повышает сложность.
|
||
* Теперь клиентам класса LogProcessor нужно решить, какую реализацию использовать,
|
||
* или переложить эту ответственность на вызывающий код.
|
||
*/
|
||
|
||
/*
|
||
* ВМЕСТО
|
||
* классической стратегии на основе наследования
|
||
* можно использовать стратегию на основе делегатов
|
||
*
|
||
* ПРИМЕР: Стратегия сортировки
|
||
*/
|
||
|
||
/*
|
||
* ВАЖНО: Гибкость не бывает бесплатной, поэтому выделять стратегии стоит тогда,
|
||
* когда действительно нужна замена поведения во время исполнения.
|
||
*/
|
||
using Strategy;
|
||
|
||
class Program
|
||
{
|
||
#region Пример №3 - Сomparer
|
||
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)); //используем делегат
|
||
}
|
||
#endregion
|
||
|
||
public static void Main(string[] args)
|
||
{
|
||
#region Пример №1 - базовое
|
||
var car = new Car(new PetrolMove());
|
||
car.Move();
|
||
car.Movable = new ElectronicMove();
|
||
car.Move();
|
||
Console.ReadKey();
|
||
#endregion
|
||
#region Пример №2 - ILogReader
|
||
LogFileReader logFileReader = new LogFileReader();
|
||
//создали делегат который принимает в себя метод,
|
||
//в результате выполнения которого возвращается List<LogEntry>
|
||
Func<List<LogEntry>> _import = () => logFileReader.Read();
|
||
LogProcessor processor = new LogProcessor(_import);
|
||
processor.ProcessLogs();
|
||
#endregion
|
||
#region Пример №3 - Сomparer
|
||
List<Employee> 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);
|
||
#endregion
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Поведение движения
|
||
/// </summary>
|
||
interface IMovable
|
||
{
|
||
void Move();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Бензиновый двигатель
|
||
/// </summary>
|
||
class PetrolMove : IMovable
|
||
{
|
||
public void Move()
|
||
{
|
||
Console.WriteLine("Движение на бензине");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Электродвигатель
|
||
/// </summary>
|
||
class ElectronicMove : IMovable
|
||
{
|
||
public void Move()
|
||
{
|
||
Console.WriteLine("Движение на электричестве");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Автомобиль
|
||
/// </summary>
|
||
class Car
|
||
{
|
||
/// <summary>
|
||
/// Cпособ передвижения автомобиля
|
||
/// </summary>
|
||
public IMovable Movable { private get; set; }
|
||
|
||
public Car(IMovable movable)
|
||
{
|
||
Movable = movable;
|
||
}
|
||
|
||
public void Move()
|
||
{
|
||
Movable.Move();
|
||
}
|
||
}
|
||
|
||
|
||
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);
|
||
}
|
||
}
|
||
} |