Новая версия данной статьи.
Думаю, не стоит писать, что же такое паттерны. Они на слуху у всех программистов. Однако, я заметил, что в последнее время кроме MVC и MVVM я ничего не использую. По большей части это из-за специфики разрабатываемых проектов. Но, так как они не используются, то и знания о них забываются и в дальнейшем, когда будет необходимо применить тот или иной паттерн, могут возникнуть сложности.
Чтобы этого не произошло, я решил повторить самые распространённые паттерны заново. Начну я с паттерна стратегия.
Стратегия(Strategy) – это поведенческий шаблон проектирования. Он предназначен для определения семейства алгоритмов, их инкапсуляции и обеспечения взаимозаменяемости.
Задача: Задачей данного паттерна является выбор подходящего алгоритма, на основе обрабатываемых данных или типу клиента.
Простейшая схема работы паттерна: 
Обычно, данный паттерн объясняется на примере уток, когда утки должны обладать определёнными свойствами (уметь летать, крякать, плавать), но каждый вид уток может обладать только определённым набором качеств. Я попробую отойти от уток и придумать что-то своё, более приближенное к реальной жизни, но при этом оставаясь учебным проектом, достаточно простым для понимания.
Проблема будет такая: на сайте есть группа пользователей, каждый из них принадлежит к определённой группе, например это администратор, редактор и гость. Каждая группа имеет свои особенности. Администраторы могут добавлять материал, удалять материал, редактировать и читать. Редакторы могут только редактировать и читать. А гости только читать. Все пользователи могут читать материал на сайте, это общая возможность для всех пользователей, остальные же возможности зависят от вида пользователя.
Для начала напишем класс User - это будет не окончательный вариант, а наброски, необходимые для дальнейшей работы.
public abstract class User
{
public void Read()
{
Console.Write("I read...");
}
public abstract void Who();
}
При вызове функции Who будет показана информация и типе текущего пользователя, при вызове Read отобразиться сообщения “I read”. Теперь необходимо разобраться с остальными правами. Рассмотрим возможность добавления материалов на сайт. Создадим интерфейс IAdding следующего вида.
public interface IAdding
{
void Add();
}
Добавим клаcc NoAdd, который будет оповещать, что пользователю запрещено добавлять материалы, наследуем его от интерфейса IAdding.
public class NoAdd:IAdding
{
public void Add()
{
Console.WriteLine("User can not add");
}
}
Теперь добавляем класс Adding, который также наследуется от IAdding, но функция Add при этом позволяет пользователю добавлять материалы.
public class Adding:IAdding
{
public void Add()
{
Console.WriteLine("Successfully added");
}
}
Классы для редактирования и удаления будет аналогичными, я не буду их описывать. Теперь пора доработать класс User.
public abstract class User
{
protected IAdding addBehaviour;
protected IEditing editBehaviour;
protected IRemoving removeBehaviour;
public User()
{
addBehaviour = new NoAdd();
editBehaviour = new NoEdit();
removeBehaviour = new NoRemove();
}
public void Read()
{
Console.WriteLine("I read...");
}
public void Add()
{
addBehaviour.Add();
}
public void Edit()
{
editBehaviour.Edit();
}
public void Remove()
{
removeBehaviour.Remove();
}
public abstract void Who();
}
Теперь добавляем классы самих пользователей. Класс администратора:
public class Administrator:User
{
public Administrator()
{
addBehaviour = new Adding();
editBehaviour = new Editing();
removeBehaviour = new Removing();
}
public override void Who()
{
Console.WriteLine("I am administrator!");
}
}
Класс класса редактора:
public class Editor:User
{
public Editor()
{
editBehaviour = new Editing();
}
public override void Who()
{
Console.WriteLine("I am editor...");
}
}
Класс гостя:
public class Guest:User
{
public override void Who()
{
Console.WriteLine("I am guest...hello...");
}
}
Осталось протестировать работу, для этого я использовал следующий код:
var users = new List();
users.Add(new Administrator());
users.Add(new Editor());
users.Add(new Guest());
foreach (var user in users)
{
user.Who();
user.Read();
user.Add();
user.Edit();
user.Remove();
Console.WriteLine("------------");
}
Результат:
Это простейшая демонстрация принципов работы паттерна «Стратегия».
Как итог можно сказать следующее: при использовании стратегии нужно отделять постоянные части от изменяемых, отдавать предпочтение композиции, а не наследованию, программировать необходимо на уровне интерфейса, а не реализации.
Исходный код учебного проекта.