策略模式
定义
策略模式定义了算法族,分别封装起来,让他们之间可以相互转换,此模式让算法的变化独立于使用算法的客户。
实例
上面的定义看起来说的不太清楚,记定义无意义,理解策略模式还是要看书中的鸭子例子。假设设计一个模拟鸭子的游戏,鸭子的种类有很多,有红头鸭、绿头鸭等等,鸭子可以划水,可以呱嘎叫。在这个模拟游戏的实现上,自然会想到用继承的方法,定义一个鸭子基类,具体的鸭子类型继承自鸭子基类。如下图所示
所有鸭子都会飞、呱呱叫和游泳,这些功能由基类来实现,display函数用来输出鸭子实例的类型,由每个子类单独实现。
但现在问题来了,因为飞、呱呱叫、游泳都由基类实现,默认所有衍生类都有和基类相同的能力。事实上不是所有的鸭子都会飞,也不是所有的鸭子都呱呱叫,例如橡皮鸭。
要解决这个问题,简单的方法有两个,第一个是方法的覆盖或隐藏基类函数,例如橡皮鸭不能飞,那么在橡皮鸭的定义里生命fly()函数,覆盖或隐藏基类的fly()函数。这种方法的缺点是,每有一个不同于基类方法的子类,都需要单独声明并定义该方法。这样做对于对于继承关系复杂的类结构,添加或修改类都需要很大的工作量。
第二个方法是,将fly()等函数封装到接口中去,子类继承自这些接口,接口中的函数在子类中分别实现。这样做工作量也很大,无法实现方法的复用。
运用策略模式解决问题
策略模式就是把一组行为,也就是一族算法封装成类.在定义新的鸭子子类时,不必为每一个子类分别定义其行为,而只需要在鸭子类中添加封装好的算法。在这个例子中,把飞和呱呱叫都封装成类,这些类独立于鸭子类,这种低耦合的方式更利于代码的维护。策略模式的另一个优点是可以更改鸭子的行为。详细内容参见下文代码。本次实例的UML类图如下所示:
C++代码
1 #include <iostream>
2 using namespace std;
3
4
5 class IFlyBehavior
6 {
7 public:
8 virtual void Fly() = 0;
9 };
10 class IQuakBehavior
11 {
12 public:
13 virtual void Quack() = 0;
14 };
15 class FlyWithWings : public IFlyBehavior
16 {
17 public:
18 void Fly()
19 {
20 cout << "I can fly" << endl;
21 }
22 };
23
24 class FlyNoWay : public IFlyBehavior
25 {
26 public:
27 void Fly()
28 {
29 cout << "sorry, I cannot fly" << endl;
30 }
31 };
32 class SQuack : public IQuakBehavior
33 {
34 public:
35 void Quack()
36 {
37 cout << "I can Quack" << endl;
38 }
39 };
40 class MuteQuack : public IQuakBehavior
41 {
42 public:
43 void Quack()
44 {
45 cout << "sorry, I cannot quack" << endl;
46 }
47 };
48 class Duck
49 {
50 public:
51 IFlyBehavior *flyBehavior;
52 IQuakBehavior *quackBehavior;
53 void Swim()
54 {
55 cout << "I can swim" << endl;
56 }
57 virtual void Display()
58 {
59 cout << "I am a duck, " ;
60 }
61 void PerformaceFly()
62 {
63 Display();
64 flyBehavior->Fly();
65 }
66 void PerformanceQuack()
67 {
68 Display();
69 quackBehavior->Quack();
70 }
71 void SetFlyBehavior(IFlyBehavior *iFly)
72 {
73 flyBehavior = iFly;
74 }
75 void SetQuackBehavior(IQuakBehavior *IQuack)
76 {
77 quackBehavior = IQuack;
78 }
79 };
80 class RedHeadDuck : public Duck
81 {
82 public:
83 RedHeadDuck()
84 {
85 flyBehavior = new FlyWithWings();
86 quackBehavior = new SQuack();
87 }
88 void Display()
89 {
90 cout << "I am a red head duck, " ;
91 }
92 ~RedHeadDuck()
93 {
94 delete flyBehavior;
95 delete quackBehavior;
96 }
97 };
98 class RubberDuck : public Duck
99 {
100 public:
101 RubberDuck()
102 {
103 flyBehavior = new FlyNoWay();
104 quackBehavior = new MuteQuack();
105 }
106 void Display()
107 {
108 cout << "I am a rubber duck, " ;
109 }
110 ~RubberDuck()
111 {
112 delete flyBehavior;
113 delete quackBehavior;
114 }
115 };
116 void main()
117 {
118 RedHeadDuck redDuck;
119 RubberDuck rubberDuck;
120
121 redDuck.PerformaceFly();
122 redDuck.PerformanceQuack();
123 cout << endl;
124
125 rubberDuck.PerformaceFly();
126 rubberDuck.PerformanceQuack();
127 cout << endl;
128
129 rubberDuck.SetFlyBehavior(new FlyWithWings());
130 rubberDuck.SetQuackBehavior(new SQuack());
131 rubberDuck.PerformaceFly();
132 rubberDuck.PerformanceQuack();
133 system("pause");
134 }
2 using namespace std;
3
4
5 class IFlyBehavior
6 {
7 public:
8 virtual void Fly() = 0;
9 };
10 class IQuakBehavior
11 {
12 public:
13 virtual void Quack() = 0;
14 };
15 class FlyWithWings : public IFlyBehavior
16 {
17 public:
18 void Fly()
19 {
20 cout << "I can fly" << endl;
21 }
22 };
23
24 class FlyNoWay : public IFlyBehavior
25 {
26 public:
27 void Fly()
28 {
29 cout << "sorry, I cannot fly" << endl;
30 }
31 };
32 class SQuack : public IQuakBehavior
33 {
34 public:
35 void Quack()
36 {
37 cout << "I can Quack" << endl;
38 }
39 };
40 class MuteQuack : public IQuakBehavior
41 {
42 public:
43 void Quack()
44 {
45 cout << "sorry, I cannot quack" << endl;
46 }
47 };
48 class Duck
49 {
50 public:
51 IFlyBehavior *flyBehavior;
52 IQuakBehavior *quackBehavior;
53 void Swim()
54 {
55 cout << "I can swim" << endl;
56 }
57 virtual void Display()
58 {
59 cout << "I am a duck, " ;
60 }
61 void PerformaceFly()
62 {
63 Display();
64 flyBehavior->Fly();
65 }
66 void PerformanceQuack()
67 {
68 Display();
69 quackBehavior->Quack();
70 }
71 void SetFlyBehavior(IFlyBehavior *iFly)
72 {
73 flyBehavior = iFly;
74 }
75 void SetQuackBehavior(IQuakBehavior *IQuack)
76 {
77 quackBehavior = IQuack;
78 }
79 };
80 class RedHeadDuck : public Duck
81 {
82 public:
83 RedHeadDuck()
84 {
85 flyBehavior = new FlyWithWings();
86 quackBehavior = new SQuack();
87 }
88 void Display()
89 {
90 cout << "I am a red head duck, " ;
91 }
92 ~RedHeadDuck()
93 {
94 delete flyBehavior;
95 delete quackBehavior;
96 }
97 };
98 class RubberDuck : public Duck
99 {
100 public:
101 RubberDuck()
102 {
103 flyBehavior = new FlyNoWay();
104 quackBehavior = new MuteQuack();
105 }
106 void Display()
107 {
108 cout << "I am a rubber duck, " ;
109 }
110 ~RubberDuck()
111 {
112 delete flyBehavior;
113 delete quackBehavior;
114 }
115 };
116 void main()
117 {
118 RedHeadDuck redDuck;
119 RubberDuck rubberDuck;
120
121 redDuck.PerformaceFly();
122 redDuck.PerformanceQuack();
123 cout << endl;
124
125 rubberDuck.PerformaceFly();
126 rubberDuck.PerformanceQuack();
127 cout << endl;
128
129 rubberDuck.SetFlyBehavior(new FlyWithWings());
130 rubberDuck.SetQuackBehavior(new SQuack());
131 rubberDuck.PerformaceFly();
132 rubberDuck.PerformanceQuack();
133 system("pause");
134 }