zoukankan      html  css  js  c++  java
  • 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 }

     

    运行结果

  • 相关阅读:
    012 数据类型基础
    013 数据类型:数字类型
    Codeforces 235C Cyclical Quest (后缀自动机)
    BZOJ 4032 Luogu P4112 [HEOI2015]最短不公共子串 (DP、后缀自动机)
    BZOJ 4278 [ONTAK2015]Tasowanie (后缀数组)
    [加强版] Codeforces 835D Palindromic characteristics (回文自动机、DP)
    BZOJ 4044 Luogu P4762 [CERC2014]Virus Synthesis (回文自动机、DP)
    BZOJ 2434 Luogu P2414 [NOI2011]阿狸的打字机 (AC自动机、树状数组)
    BZOJ 2754 [SCOI2012]喵星球上的点名 (AC自动机、树状数组)
    BZOJ 4327 [JSOI2012]玄武密码 (AC自动机)
  • 原文地址:https://www.cnblogs.com/wangke1020/p/3736470.html
Copyright © 2011-2022 走看看