設(shè)計模式之Strategy模式
Strategy模式是設(shè)計模式中非常常用的一種設(shè)計模式,甚至在你沒有學(xué)習(xí)過設(shè)計模式之前就已經(jīng)使用過這種模式。先看個簡單的例子吧:比如說你要寫個List的容器,需要有一個Sort方法。但是對于容器中不同類型的對象Sort方法可能會不一樣,比如說Point類型可能根據(jù)point到原點的距離或者point的xy之和來比較大小。
一種很自然的想法就是:
1
void sort()
2

{
3
//按到原點距離排序
4
if()
5
{}
6
//按XY之和大小排序
7
else if()
8
{}
9
}
但是說不定哪天Boss說:“我要按X的大小排序,你把Sort重寫一下”,這難道不是讓人抓狂?
2



3

4

5



6

7

8



9

好在我們有Stratregy模式能搞定這類變化問題(設(shè)計模式的根本目的就是在于抑制變化對程序的影響)
動機:
軟件構(gòu)建中,某些對象使用的算法可能多種多樣,我們需要的是將算法和對象本身解耦,在運行時根據(jù)需要透明地更改對象的算法。
意圖:
定義一系列的算法,把他們一個個封裝起來,并且使他們可以相互替換。該模式使得算法可以獨立于它的客戶而變化。(GoF23)
設(shè)計思路:
我們的目的是讓Context能在各種Algorithm之間切換,如下圖:

上圖就是設(shè)計Sort時所用的最容易想到的方法,Context和三種Algorithm之間是緊耦合關(guān)系,對于需求的變化無能為力。
下圖仍然運用的是OO中的“依賴倒置原則”,使用接口將算法和對象解耦,抽象出描述算法功能要求的IStrategy接口。這樣Context和IStrategy成為相對穩(wěn)定的松耦合關(guān)系,運行時多態(tài)來控制到底運用何種算法來解決實際問題,而避免了if...else...的靜態(tài)控制。
總結(jié):
1.“依賴倒置原則”,抽象出接口,使得Context“間接”依賴算法,兩者由緊耦合變?yōu)樗婉詈稀?br>2.對于不同的算法,分別封裝成為具體類,實現(xiàn)接口要求的功能(多態(tài)應(yīng)用)。
3.Strategy模式簡單說就是實現(xiàn)了算法的“靜態(tài)切換”到“動態(tài)切換”的轉(zhuǎn)變(不光是算法,其他也都可以)。大多數(shù)情況下的if...else...和switch...case...(靜態(tài)切換)都能用Strategy模式(動態(tài)切換)來替換,這也是Strategy模式廣泛使用的原因。
關(guān)于釋放內(nèi)存:
非常感謝有朋友指出我代碼中存在的問題
主要的問題是如何對Context中的釋放IS指針指向的內(nèi)存,具體還是看代碼中的Method函數(shù)和析構(gòu)函數(shù),如果還有問題歡迎繼續(xù)指正 :-)
(指針初始化賦NULL,delete后仍然賦NULL,養(yǎng)成好習(xí)慣:-))
自己做的示例代碼,僅供參考
1
/**///////////////////////////////////////////////////////////////////////////
2
//StrategyTest For Strategy Pattern
3
//
4
/**///////////////////////////////////////////////////////////////////////////
5
6
#include "stdafx.h"
7
#include <iostream>
8
using namespace std;
9
10
//策略類,不同算法的抽象接口
11
class IStrategy
12

{
13
public:
14
virtual void process()=0;
15
};
16
17
//算法的具體實現(xiàn)
18
class StrategyA:public IStrategy
19

{
20
public:
21
void process()
22
{
23
cout<<"StrategyA
"<<endl;
24
}
25
};
26
27
class StrategyB:public IStrategy
28

{
29
public:
30
void process()
31
{
32
cout<<"StrategyB
"<<endl;
33
}
34
};
35
36
class StrategyC:public IStrategy
37

{
38
public:
39
void process()
40
{
41
cout<<"StrategyC
"<<endl;
42
}
43
};
44
45
//需要切換算法的上下文類
46
class Context
47

{
48
private:
49
IStrategy* IS;
50
public:
51
//構(gòu)造函數(shù)
52
Context()
53
{
54
IS = NULL;
55
}
56
//使用不同類型的算法
57
void method(IStrategy *IS)
58
{
59
//首先檢查指針是否為空,不為空則釋放指針
60
if ((this->IS) != NULL)
61
{
62
delete (this->IS);
63
this->IS = NULL;
64
}
65
//對指針賦值
66
this->IS = IS;
67
/**///////////////////////////////////////////////////////////////////////////
68
//一些操作
69
/**///////////////////////////////////////////////////////////////////////////
70
71
//調(diào)用算法
72
this->IS->process();
73
}
74
//析構(gòu)函數(shù),釋放指針
75
~Context()
76
{
77
if (this->IS != NULL)
{ delete this->IS; }
78
}
79
};
80
81
int _tmain(int argc, _TCHAR* argv[])
82

{
83
Context* context = new Context();
84
85
//Context使用算法A
86
cout<<"Context use the AlgorithmA: "<<endl;
87
context->method(new StrategyA());
88
89
//Context使用算法B
90
cout<<"Context use the AlgorithmB: "<<endl;
91
context->method(new StrategyB());
92
93
//Context使用算法C
94
cout<<"Context use the AlgorithmC: "<<endl;
95
context->method(new StrategyC());
96
97
return 0;
98
}


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

98

posted on 2009-04-06 15:21 Alex@VCC 閱讀(3166) 評論(7) 編輯 收藏 引用 所屬分類: 設(shè)計模式