Стратегия — это поведенческий паттерн, выносит набор алгоритмов в собственные классы и делает их взаимозаменимыми.
Другие объекты содержат ссылку на объект-стратегию и делегируют ей работу. Программа может подменить этот объект другим, если требуется иной способ решения задачи.
Сложность:
Популярность:
Применимость: Стратегия часто используется в C#-коде, особенно там, где нужно подменять алгоритм во время выполнения программы. Многие примеры стратегии можно заменить простыми lambda-выражениями.
Признаки применения паттерна: Класс делегирует выполнение вложенному объекту абстрактного типа или интерфейса.
Концептуальный пример
Этот пример показывает структуру паттерна Стратегия , а именно — из каких классов он состоит, какие роли эти классы выполняют и как они взаимодействуют друг с другом.
Program.cs: Пример структуры паттерна
using System;
using System.Collections.Generic;
namespace RefactoringGuru.DesignPatterns.Strategy.Conceptual
{
// Контекст определяет интерфейс, представляющий интерес для клиентов.
class Context
{
// Контекст хранит ссылку на один из объектов Стратегии. Контекст не
// знает конкретного класса стратегии. Он должен работать со всеми
// стратегиями через интерфейс Стратегии.
private IStrategy _strategy;
public Context()
{ }
// Обычно Контекст принимает стратегию через конструктор, а также
// предоставляет сеттер для её изменения во время выполнения.
public Context(IStrategy strategy)
{
this._strategy = strategy;
}
// Обычно Контекст позволяет заменить объект Стратегии во время
// выполнения.
public void SetStrategy(IStrategy strategy)
{
this._strategy = strategy;
}
// Вместо того, чтобы самостоятельно реализовывать множественные версии
// алгоритма, Контекст делегирует некоторую работу объекту Стратегии.
public void DoSomeBusinessLogic()
{
Console.WriteLine("Context: Sorting data using the strategy (not sure how it'll do it)");
var result = this._strategy.DoAlgorithm(new List<string> { "a", "b", "c", "d", "e" });
string resultStr = string.Empty;
foreach (var element in result as List<string>)
{
resultStr += element + ",";
}
Console.WriteLine(resultStr);
}
}
// Интерфейс Стратегии объявляет операции, общие для всех поддерживаемых
// версий некоторого алгоритма.
//
// Контекст использует этот интерфейс для вызова алгоритма, определённого
// Конкретными Стратегиями.
public interface IStrategy
{
object DoAlgorithm(object data);
}
// Конкретные Стратегии реализуют алгоритм, следуя базовому интерфейсу
// Стратегии. Этот интерфейс делает их взаимозаменяемыми в Контексте.
class ConcreteStrategyA : IStrategy
{
public object DoAlgorithm(object data)
{
var list = data as List<string>;
list.Sort();
return list;
}
}
class ConcreteStrategyB : IStrategy
{
public object DoAlgorithm(object data)
{
var list = data as List<string>;
list.Sort();
list.Reverse();
return list;
}
}
class Program
{
static void Main(string[] args)
{
// Клиентский код выбирает конкретную стратегию и передаёт её в
// контекст. Клиент должен знать о различиях между стратегиями,
// чтобы сделать правильный выбор.
var context = new Context();
Console.WriteLine("Client: Strategy is set to normal sorting.");
context.SetStrategy(new ConcreteStrategyA());
context.DoSomeBusinessLogic();
Console.WriteLine();
Console.WriteLine("Client: Strategy is set to reverse sorting.");
context.SetStrategy(new ConcreteStrategyB());
context.DoSomeBusinessLogic();
}
}
}
Output.txt: Результат выполнения
Client: Strategy is set to normal sorting.
Context: Sorting data using the strategy (not sure how it'll do it)
a,b,c,d,e
Client: Strategy is set to reverse sorting.
Context: Sorting data using the strategy (not sure how it'll do it)
e,d,c,b,a