设计模式(5) 对象行为型模式 Strategy 策略设计模式

目录

1. 意图

定义一系列算法并封装,使它们可相互替换。算法可独立于使用它的客户而变化。

2. 别名

Policy

3. 动机

考虑许多算法对一个正文流进行分析,不可将算法直接code进使用他们的类。

如下图,定义一些类来封装不同的换行算法。

Composition类维护和更新正文换行,但换行策略是由抽象的Composition的子类各自独立完成。Composition维护对Compositor对象的一个引用。一旦Composition重新格式化其正文,将这个职责转发给它的Compositor对象。Composition的客户指定使用哪一种Compositor的方法就是将想要的Compositor装入Composition

4. 适用性

  • 许多相关的类仅仅是行为有差异。此模式提供一种用多个可选行为中的一个行为配置一个类的方法。
  • 需要使用一个算法的不同变体。同上
  • 算法使用client不不应该知道的数据。可以隐藏复杂的、与算法相关的数据结构
  • 一个类中的多种行为操作以多个条件语句形式出现,可以将各个条件分支移入各自的Strategy类以代替条件语句

5. 结构

6. 参与者

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

7. 协作

  • Strategy和Context相互作用以实现选定的算法。
  • Context将它的客户的请求转发给它的Strategy。

8. 效果

优点

  1. 相关算法系列
  2. 一个替代继承的方法
  3. 消除一些条件语句
  4. 实现有多种选择

缺点

  1. 客户必须了解不同的Strategy以选择一个合适的Strategy,这将向用户暴露具体的实现问题。
  2. Strategy和Context之间的通信开销。
  3. 增加对象的数量。

9. 实现

  • 定义Strategy和Context接口
  • 使用Strategy作为模板参数
  • 使Strategy对象可选

10. 代码示例

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
//将值传给Compositor,它使用这些值决定换行的最佳位置
class Composition {
public:
composition(Compositor*);
void Repair();
private:
Compositor* _compositor;
component* _ components;
int _componentCount;
int _lineWidth;
int* _lineCount;
};

//抽象类,具体子类定义特定的换行策略
class Compositor{
public:
virtual int Compose(Coord natural[], Coord stretch[], Coord shrink[], int componentCount, int lineWidth, int breaks[]) = 0;
protected:
Compositor();
};

//具体子类一
class SimpleCompositor : public Compositor {
public:
SimpleCompositor();

virtual int Compose(Coord natural[], Coord stretch[], Coord shrink[], int componentCount, int lineWidth, int breaks[]);
};

//具体子类二
class TeXCompositor : public Compositor {
public:
TeXCompositor();

virtual int Compose(Coord natural[], Coord stretch[], Coord shrink[], int componentCount, int lineWidth, int breaks[]);
};

//实例化Composition需要把想要使用的Compositor传递给它
Composition* quick = new Composition(new SimpleCompositor);
Composition* slick = new Composition(new TeXCompositor);

11. 已知应用

ET++和InterViews

0%