一、 策略(Strategy)模式
策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。
使用策略模式可以把行为和环境分割开来,
二、 策略模式的结构
策略模式是对算法的包装,是把使用算法的责任和算法本身分割开,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:"准备一组算法,并将每一个算法封装起来,使得它们可以互换。"
策略又称做政策(Policy)模式【GOF95】。下面是一个示意性的策略模式结构图:
这个模式涉及到三个角色:
- 环境(Context)角色:持有一个Strategy类的引用。
- 抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
- 具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
看例子:
//抽象算法类
abstract class Strategy
{
//算法方法
public abstract void AlgorithmInterface();
}
//具体算法A
class ConcreteStrategyA : Strategy
{
//算法A实现方法
public override void AlgorithmInterface()
{
Console.WriteLine("算法A实现");
}
}
//具体算法B
class ConcreteStrategyB : Strategy
{
//算法B实现方法
public override void AlgorithmInterface()
{
Console.WriteLine("算法B实现");
}
}
//具体算法C
class ConcreteStrategyC : Strategy
{
//算法C实现方法
public override void AlgorithmInterface()
{
Console.WriteLine("算法C实现");
}
}
//上下文
class Context
{
Strategy strategy;
public Context(Strategy _strategy)
{
this.strategy = _strategy;
}
//上下文接口
public void ContextInterface()
{
strategy.AlgorithmInterface();
}
}
下面我们来控制台测试下:
static void Main(string[] args)
{
Context context;
context = new Context(new ConcreteStrategyA());
context.ContextInterface();
context = new Context(new ConcreteStrategyB());
context.ContextInterface();
context = new Context(new ConcreteStrategyC());
context.ContextInterface();
Console.Read();
}
运行结果如下:
三、 在什么情况下应当使用策略模式
在下面的情况下应当考虑使用策略模式:
1. 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
2. 一个系统需要动态地在几种算法中选择一种。那么这些算法可以包装到一个个的具体算法类里面,而这些具体算法类都是一个抽象算法类的子类。换言之,这些具体算法类均有统一的接口,由于多态性原则,客户端可以选择使用任何一个具体算法类,并只持有一个数据类型是抽象算法类的对象。
3. 一个系统的算法使用的数据不可以让客户端知道。策略模式可以避免让客户端涉及到不必要接触到的复杂的和只与算法有关的数据。
4. 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。此时,使用策略模式,把这些行为转移到相应的具体策略类里面,就可以避免使用难以维护的多重条件选择语句,并体现面向对象设计的概念。