设计模式探秘-15-策略模式

策略模式的学习与实践

策略模式

策略模式定义:定义一组算法,将每个算法封装起来,并且使它们之间可以互相互换。

类图

  1. Context 封装角色(上下文角色),起承上启下封装作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。
  2. Strategy 抽象策略角色 策略、算法家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性。
  3. ConcreteStrategy 具体策略角色 实现抽象策略中的操作,该类含有具体的算法。

优点

  1. 算法可以自由切换 策略模式本身定义的,只要实现抽象策略,即为策略家族的一个成员,通过封装角色对其进行封装,保证对外提供
    可自由切换的策略。
  2. 必买年使用多重条件判断。
  3. 扩展性良好

缺点

  1. 策略类数量增多,每个策略都是一个类,复用的可能性低
  2. 所有的策略类都需要对外暴露

使用场景

  1. 多个类只是在算法或行为上稍有不同的场景
  2. 算法需要自由切换的场景
  3. 需要屏蔽算法规则的场景

注意事项

如果系统中一个策略家族的具体策略数量超过4个,则需要考虑混合模式,解决策略类膨胀和对外暴露的问题。

扩展

实践

简单实现

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <iostream>

using namespace std;

class Strategy
{
public:
Strategy()
{
}
virtual ~Strategy()
{
cout<<__FUNCTION__<<endl;
}
virtual void AlgrithmInterface() = 0;
};

class StrategyA : public Strategy
{
public:
StrategyA()
{
}
virtual ~StrategyA()
{
cout<<__FUNCTION__<<endl;
}
void AlgrithmInterface()
{
cout<<"A "<<__FUNCTION__<<endl;
}
};

class StrategyB : public Strategy
{
public:
StrategyB()
{
}
virtual ~StrategyB()
{
cout<<__FUNCTION__<<endl;
}
void AlgrithmInterface()
{
cout<<"B "<<__FUNCTION__<<endl;
}
};

class Context
{
public:
Context(Strategy *stg)
{
SetStg(stg);
}
~Context()
{
if(m_pStg != nullptr)
{
delete m_pStg;
}
}
void DoAction()
{
if(m_pStg != nullptr)
{
m_pStg->AlgrithmInterface();
}
}
void SetStg(Strategy *stg)
{
if(m_pStg != nullptr)
{
delete m_pStg;
m_pStg = nullptr;
}
m_pStg = stg;
}
private:
Strategy *m_pStg;
};

int main()
{
Context *pc = new Context(new StrategyA());
pc->DoAction();
pc->SetStg(new StrategyB());
pc->DoAction();
if(pc != nullptr)
{
delete pc;
pc = nullptr;
}

return 0;
}

参考资料

  1. 设计模式之禅
  2. GoF+23种设计模式解析