意图
- 定义一系列算法,把它们一个个封装起来,并且使他们它们可以互相替换。本模式使得算法可独立于使用它的客户而变化
适用性
- 许多相关的类仅仅是行为有异。策略模式提供了一种用多个行为中的一个行为来配置一个类的方法;
- 需要适用一个算法的不同变体
- 算法使用客户不应该知道的数据。
- 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现。
结构
参与者
-
Strategy
-
定义所有支持的算法的公共接口
-
ConcreteStrategy
-
以Strategy接口实现某具体算法
-
Context
-
用一个ConcreteStrategy对象来配置
-
维护一个对Strategy对象的引用
-
可定义一个接口来让Strategy访问它的数据
协作
-
Strategy和Context相互作用实现选定的算法。当算法被调用时,Context可以将该算法所需要的所有数据都传递给该strategy。或者Context可以将自身作为一个参数传递给Strategy操作。这就让Strategy在需要时可以回调Context.
-
Context将它的客户的请求转发给它的strategy。客户通常并传递一个concreteStrategy对象给Context;这样客户仅与Context交互,通常有一系列的ConcreteStrategy类供客户从中选择。
效果
-
相关算法系列 Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法中的公共功能。
-
一个替代继承的方法 继承提供了另一种支持多种算法或行为的方法
-
消除了一些条件语句 Strategy模式提供了用条件语句所需的行为以外的另一种选择。
-
实现的选择,Strategy模式可以提供相同行为的不同实现。
-
客户必须了解不同的strategy。
-
Strategy和Context之间的通信开销。
-
增加了对象的数目
实现
- 定义了Strategy和Context接口,Strategy和Context接口必须使得ConcreteStrategy能够有效地访问它所需要的Context中的任务数据,反之亦然。一种办法是让Context将数据放在参数中传递给Strategy操作,也就是说将数据发送给Strategy。
- 将 Strategy作为模板参数
- 使Strategy对象成为可选的
实现
class StrategyStructure
{
public void Test()
{
Strategy strA = new ConcreteStarategyA();
Strategy strB = new ConcreteStarategyB();
Context context = new Context();
context.Strategy = strA;
context.Operation();
context.Strategy = strB;
context.Operation();
}
}
abstract class Strategy
{
public abstract void AlgorithmInterface( Context context);
}
class ConcreteStarategyA :Strategy
{
public override void AlgorithmInterface(Context context)
{
Console.WriteLine(context.GetType().Name + " in "+this.GetType().Name+" 执行");
}
}
class ConcreteStarategyB : Strategy
{
public override void AlgorithmInterface(Context context)
{
Console.WriteLine(context.GetType().Name + " in " + this.GetType().Name + " 执行");
}
}
class Context
{
private Strategy _strategy;
public Strategy Strategy {
set { _strategy = value; }
}
public void Operation()
{
_strategy.AlgorithmInterface(this);
}
}
相关算法
Flyeight:Strategy使很好的轻量级对象;