Usage examples: The Strategy pattern is very common in C# code. It’s often used in various frameworks to provide users a way to change the behavior of a class without extending it.
Identification: Strategy pattern can be recognized by a method that lets a nested object do the actual work, as well as a setter that allows replacing that object with a different one.
Conceptual Example
This example illustrates the structure of the Strategy design pattern. It focuses on answering these questions:
What classes does it consist of?
What roles do these classes play?
In what way the elements of the pattern are related?
Program.cs: Conceptual example
usingSystem;usingSystem.Collections.Generic;namespaceRefactoringGuru.DesignPatterns.Strategy.Conceptual{ // The Context defines the interface of interest to clients.classContext { // The Context maintains a reference to one of the Strategy objects. The // Context does not know the concrete class of a strategy. It should // work with all strategies via the Strategy interface.privateIStrategy _strategy;publicContext() { } // Usually, the Context accepts a strategy through the constructor, but // also provides a setter to change it at runtime.publicContext(IStrategy strategy) {this._strategy= strategy; } // Usually, the Context allows replacing a Strategy object at runtime.publicvoidSetStrategy(IStrategy strategy) {this._strategy= strategy; } // The Context delegates some work to the Strategy object instead of // implementing multiple versions of the algorithm on its own.publicvoidDoSomeBusinessLogic() {Console.WriteLine("Context: Sorting data using the strategy (not sure how it'll do it)");var result =this._strategy.DoAlgorithm(newList<string> { "a","b","c","d","e" });string resultStr =string.Empty;foreach (var element in result asList<string>) { resultStr += element +","; }Console.WriteLine(resultStr); } } // The Strategy interface declares operations common to all supported // versions of some algorithm. // // The Context uses this interface to call the algorithm defined by Concrete // Strategies.publicinterfaceIStrategy {objectDoAlgorithm(object data); } // Concrete Strategies implement the algorithm while following the base // Strategy interface. The interface makes them interchangeable in the // Context.classConcreteStrategyA:IStrategy {publicobjectDoAlgorithm(object data) {var list = data asList<string>;list.Sort();return list; } }classConcreteStrategyB:IStrategy {publicobjectDoAlgorithm(object data) {var list = data asList<string>;list.Sort();list.Reverse();return list; } }classProgram {staticvoidMain(string[] args) { // The client code picks a concrete strategy and passes it to the // context. The client should be aware of the differences between // strategies in order to make the right choice.var context =newContext();Console.WriteLine("Client: Strategy is set to normal sorting.");context.SetStrategy(newConcreteStrategyA());context.DoSomeBusinessLogic();Console.WriteLine();Console.WriteLine("Client: Strategy is set to reverse sorting.");context.SetStrategy(newConcreteStrategyB());context.DoSomeBusinessLogic(); } }}
Output.txt: Execution result
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