Strategy

策略模式

策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

适用性

许多相关的类仅仅是行为有异。策略提供了一种用多个行为中的一个行为来配置一个类的方法。
需要使用一个算法的不同变体。
算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。

结构

Strategy Class

Strategy - 定义所有支持的算法的公共接口。Context使用这个借口来调用某ConcreteStrategy定义的算法。
ConcreteStrategy - 以Strategy接口实现某具体算法。
Context - 用一个ConcreteStrategy对象来配置。维护一个对Strategy对象的引用。可定义一个接口来让Strategy访问它的数据。

协作:
Strategy和Context相互作用以实现选定的算法。当算法被调用时,Context可以将该算法所需要的所有数据都传递给该Strategy。或者,Context可以将自身作为一个参数传递给Strategy操作。这就让Strategy在需要时可以回调Context。
Context将它的客户的请求转发给它的Strategy。客户通常创建并传递一个ConcreteStrategy对象给该Context; 这样,客户仅与Context交互。通常有一系列的ConcreteStrategy类可供客户从中选择。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>
//---------------------------------------------------
class Strategy
{
public:
virtual void algorithm_interface() = 0;
};
//---------------------------------------------------
class ConcreteStrategyA : public Strategy
{
public:
virtual void algorithm_interface()
{

std::cout << "ConcreteStrategyA" << std::endl;
}
};
//---------------------------------------------------
class ConcreteStrategyB : public Strategy
{
public:
virtual void algorithm_interface()
{

std::cout << "ConcreteStrategyB" << std::endl;
}
};
//---------------------------------------------------
class Context
{
public:
Context(Strategy* s) : m_strategy(s) {}
virtual void context_interface()
{

if (!m_strategy) return;
m_strategy->algorithm_interface();
}
void set_strategy(Strategy* s) {m_strategy = s;}
protected:
Strategy* m_strategy;
};
//---------------------------------------------------
int main()
{

ConcreteStrategyA a;
ConcreteStrategyB b;
Context c(&a);
c.context_interface();
c.set_strategy(&b);
c.context_interface();
system("Pause");
}

相关模式

  • Flyweight: Strategy对象经常是很好的轻量级对象。

[1] 设计模式:可复用面向对象软件的基础
[2] Head First设计模式