Стратегия на C#
Стратегия — это поведенческий паттерн, выносит набор алгоритмов в собственные классы и делает их взаимозаменимыми.
Другие объекты содержат ссылку на объект-стратегию и делегируют ей работу. Программа может подменить этот объект другим, если требуется иной способ решения задачи.
Сложность:
Популярность:
Применимость: Стратегия часто используется в 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