1. 模式意图
策略模式别名Policy。
策略模式的意图是针对一组算法,将每个算法封装到具有共同接口的独立的类中,从而使得他们可以相互替换。
策略模式使得算法可以在不影响客户端的情况下发生变化。
使用策略模式可以把行为和环境分割开来。环境类负责维持和查询行为类,各种算法则在具体策略类中提供。由于算法和环境独立开来,算法的增减、修改都不会影响环境和客户端。当出现新的变化时,只需要实现新的策略类,并在客户端登记即可。
Note:策略模式并不决定何时使用何种算法(策略)
策略模式 V.S. 桥接模式:
- Strategy模式注重于算法的封装;
- Bridge模式注重于分离抽象和实现,为一个抽象体系提供不同的实现;
2. 模式定义
Context(上下文,环境): 用一个ConcreteStrategy对象来配置;维护一个对Strategy对象的引用;可定义一个接口让Strategy访问它的数据;
抽象策略(Strategy): 定义一个接口或抽象类实现;定义所有支持的算法的公共接口;Context使用这个接口来调用某ConcreteStrategy定义的算法;
具体策略(ConcreteStretegy): 以Strategy接口实现某具体算法;
3. 模式实现
3.1 C#实现策略模式
// Strategy pattern -- Structural example
using System;// "Strategy"
abstract class Strategy
{// Methodsabstract public void AlgorithmInterface();
}// "ConcreteStrategyA"
class ConcreteStrategyA : Strategy
{// Methodsoverride public void AlgorithmInterface(){Console.WriteLine("Called ConcreteStrategyA.AlgorithmInterface()");}
}// "ConcreteStrategyB"
class ConcreteStrategyB : Strategy
{// Methodsoverride public void AlgorithmInterface(){Console.WriteLine("Called ConcreteStrategyB.AlgorithmInterface()");}
}// "ConcreteStrategyC"
class ConcreteStrategyC : Strategy
{// Methodsoverride public void AlgorithmInterface(){Console.WriteLine("Called ConcreteStrategyC.AlgorithmInterface()");}
}// "Context"
class Context
{// FieldsStrategy strategy;// Constructorspublic Context( Strategy strategy ){this.strategy = strategy;}// Methodspublic void ContextInterface(){strategy.AlgorithmInterface();}
}/// <summary>
/// Client test
/// </summary>
public class Client
{public static void Main( string[] args ){// Three contexts following different strategiesContext c = new Context( new ConcreteStrategyA() );c.ContextInterface();Context d = new Context( new ConcreteStrategyB() );d.ContextInterface();Context e = new Context( new ConcreteStrategyC() );e.ContextInterface();}
}
4. 模式应用
4.1 何时使用策略模式
- 如果在一个系统里面有许多类,他们之间的区别仅在于他们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
- 一个系统需要动态地在几种算法中选择几种。那么这些算法可以包装到一个个的具体的算法类里面,而这些具体算法类都是一个抽象算法类的子类。换言之,这些具体算法类均有统一的接口,由于多态原则,客户端可以选择使用任何一个具体算法类,并只持有一个抽象算法类的对象。
- 一个系统的算法使用的数据不可以让客户端知道;策略模式可以避免让客户端涉及到不必要接触到的复杂的和只与算法有关的数据。
- 如果一个对象有很多的行为,如果使用不恰当的模式,这些行为就只好使用多重的条件选择语句来实现。此时,使用策略模式,把这些行为转移到相应的具体策略类里面,就可以避免使用难以维护的多重条件选择语句,并体现面向对象设计的概念。