Head First 设计模式之一 策略模式

策略模式

 

定义

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

 

实例

上面的定义看起来说的不太清楚,记定义无意义,理解策略模式还是要看书中的鸭子例子。假设设计一个模拟鸭子的游戏,鸭子的种类有很多,有红头鸭、绿头鸭等等,鸭子可以划水,可以呱嘎叫。在这个模拟游戏的实现上,自然会想到用继承的方法,定义一个鸭子基类,具体的鸭子类型继承自鸭子基类。如下图所示

所有鸭子都会飞、呱呱叫和游泳,这些功能由基类来实现,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 }

 

运行结果

原文地址:https://www.cnblogs.com/wangke1020/p/3736470.html