意图 intent :定义一系列的算法 , 把它们一个个封装起来 , 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
适用性:
许多相关的类仅仅是行为有异。“ 策略” 提供了一种用多个行为中的一个行为来配置一个类的方法。 需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间/ 时间权衡的算法。当这些变体实现为一个算法的类层次时[H087] , 可以使用策略模式。 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。 一个类定义了多种行为, 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的Strategy 类中以代替这些条件语句。
Definition :
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
participants
The classes and/or objects participating in this pattern are:
Strategy (SortStrategy) declares an interface common to all supported algorithms. Context uses this interface to call the algorithm defined by a ConcreteStrategy
ConcreteStrategy (QuickSort, ShellSort, MergeSort) implements the algorithm using the Strategy interface
Context (SortedList) is configured with a ConcreteStrategy object maintains a reference to a Strategy object may define an interface that lets Strategy access its data.
对象可能经常需要使用多种不同的算法,但是如果变化频繁,会将类型变得脆弱。。。在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担。如何在运行时根据需要透明地更改对象的算法?将算法与对象本身解耦,从而避免上述问题?
Strategy 及其子类为组件提供了一系列可重用的算法,从而可以使得类型在运行时方便地根据需要在各个算法之间进行切换。所谓封装算法,支持算法的变化。 Strategy 模式提供了用条件判断语句以外的另一种选择,消除条件判断语句,就是在解耦合。含有许多条件判断语句的代码通常都需要 strategy 模式。与 state 类似,如果 strategy 对象没有实例变量,那么各个上下文可以共享同一个 strategy 对象,从而节省对象开销。
Sample code in c#
This structural code demonstrates the Strategy pattern which encapsulates functionality in the form of an object. This allows clients to dynamically change algorithmic strategies.
// Strategy pattern -- Structural example
using System; namespace DoFactory.GangOfFour.Strategy.Structural { // MainApp test application class MainApp { static void Main() { Context context; // Three contexts following different strategies context = new Context(new ConcreteStrategyA()); context.ContextInterface(); context = new Context(new ConcreteStrategyB()); context.ContextInterface(); context = new Context(new ConcreteStrategyC()); context.ContextInterface(); // Wait for user Console.Read(); } } // "Strategy" abstract class Strategy { public abstract void AlgorithmInterface(); } // "ConcreteStrategyA" class ConcreteStrategyA : Strategy { public override void AlgorithmInterface() { Console.WriteLine( "Called ConcreteStrategyA.AlgorithmInterface()"); } } // "ConcreteStrategyB" class ConcreteStrategyB : Strategy { public override void AlgorithmInterface() { Console.WriteLine( "Called ConcreteStrategyB.AlgorithmInterface()"); } } // "ConcreteStrategyC" class ConcreteStrategyC : Strategy { public override void AlgorithmInterface() { Console.WriteLine( "Called ConcreteStrategyC.AlgorithmInterface()"); } } // "Context" class Context { Strategy strategy; // Constructor public Context(Strategy strategy) { this .strategy = strategy; } public void ContextInterface() { strategy.AlgorithmInterface(); } } }
Output
Called ConcreteStrategyA.AlgorithmInterface()
Called ConcreteStrategyB.AlgorithmInterface()
Called ConcreteStrategyC.AlgorithmInterface()
This real-world code demonstrates the Strategy pattern which encapsulates sorting algorithms in the form of sorting objects. This allows clients to dynamically change sorting strategies including Quicksort, Shellsort, and Mergesort.
// Strategy pattern -- Real World example
using System; using System.Collections; namespace DoFactory.GangOfFour.Strategy.RealWorld { // MainApp test application class MainApp { static void Main() { // Two contexts following different strategies SortedList studentRecords = new SortedList(); studentRecords.Add("Samual"); studentRecords.Add("Jimmy"); studentRecords.Add("Sandra"); studentRecords.Add("Vivek"); studentRecords.Add("Anna"); studentRecords.SetSortStrategy(new QuickSort()); studentRecords.Sort(); studentRecords.SetSortStrategy(new ShellSort()); studentRecords.Sort(); studentRecords.SetSortStrategy(new MergeSort()); studentRecords.Sort(); // Wait for user Console.Read(); } } // "Strategy" abstract class SortStrategy { public abstract void Sort(ArrayList list); } // "ConcreteStrategy" class QuickSort : SortStrategy { public override void Sort(ArrayList list) { list.Sort(); // Default is Quicksort Console.WriteLine("QuickSorted list "); } } // "ConcreteStrategy" class ShellSort : SortStrategy { public override void Sort(ArrayList list) { //list.ShellSort(); not-implemented Console.WriteLine("ShellSorted list "); } } // "ConcreteStrategy" class MergeSort : SortStrategy { public override void Sort(ArrayList list) { //list.MergeSort(); not-implemented Console.WriteLine("MergeSorted list "); } } // "Context" class SortedList { private ArrayList list = new ArrayList(); private SortStrategy sortstrategy; public void SetSortStrategy(SortStrategy sortstrategy) { this .sortstrategy = sortstrategy; } public void Add(string name) { list.Add(name); } public void Sort() { sortstrategy.Sort(list); // Display results foreach (string name in list) { Console.WriteLine(" " + name); } Console.WriteLine(); } } }
Output
QuickSorted list
Anna
Jimmy
Samual
Sandra
Vivek
ShellSorted list
Anna
Jimmy
Samual
Sandra
Vivek
MergeSorted list
Anna
Jimmy
Samual
Sandra
Vivek