C ++策略模式

时间:2011-09-06 18:32:24

标签: c++ design-patterns strategy-pattern

过去,我已经看到策略模式被解释为一种机制,允许函数/类的用户为该函数/类提供自己的功能。

我一直被告知,实现模式的方法是将函数指针引入您的类/函数并在内部调用它们,从而允许程序员提供自己的“策略”,这些策略将由这些函数内部使用。对象。

最近看一下,我看到策略模式似乎总是通过使用继承层次结构来解释/定义,如下所示:

Strategy pattern implementation

这是意见/实施的不同,还是功能指针传递的不是战略模式的变化?我最感兴趣的是,当我评论或解释我的代码时,我不会混淆人们:)

6 个答案:

答案 0 :(得分:21)

您只需在没有函数指针的语言中使用继承(读取:Java)。

就个人而言,我更喜欢std::function而不是原始函数指针,因为它接受更广泛的参数,并允许您在策略对象中维护状态。

此外,如果您已经在编译时知道策略,您甚至可以使用模板,从而节省了函数指针和std::function对象的空间和运行时开销。

答案 1 :(得分:17)

在我看来,使用函数指针实现策略模式是在不支持OOP的语言中完成的(例如C)。

在支持OOP的语言中,使用类更好地实现:继承,虚函数(即运行时多态),接口等。通常,这是运行时策略模式,这意味着,您可以在运行时切换到其他策略模式来更改程序的行为。

在C ++中,还有一个编译时策略模式,通常称为policy-based design

在任何情况下,类都可以维护状态,而函数指针则不能。这是使用类的最大优势。

答案 2 :(得分:9)

使用函数指针实现策略是基于继承的版本的退化情况。如您所知,模式的基本内核是能够在运行时提供或修改某个进程的组件。该组件可以是一个函数,也可以是一个对象。如果策略由几个位组成,则基于继承的版本确实更好,因为对象可以将多个方法打包在一起;如果只有一个,那么函数指针就好了。

答案 3 :(得分:2)

接口对象可以具有状态,因此可以维护成员变量。函数指针不能。

答案 4 :(得分:1)

IMO,starategy模式可以使用:

实现
  • 模板和编译时常量表达式(早期绑定,实际上可能不会被称为 strategy-pattern )。
  • 虚函数机制(是的,通过将不同的派生类分配给引用/指针)。
  • 功能指针
  • 类的指针成员(方法)。
  • 使用std :: function,并使用lambdas。

答案 5 :(得分:0)

这是c ++中策略模式的实用代码。我希望纯粹的虚拟功能用法(而不是Java中的接口)可以自我解释。

#include <iostream>
#include <fstream>
#include <string.h>

using namespace std;

class Strategy;

class TestBed{
  public:
    TestBed(){
        myStrategy = NULL;
    }
    void setBehavior(int type);
    Strategy *myStrategy;
};

class Strategy{
  public:
    void performBehavior(){
       behave();
    }
  private:
    virtual void behave() = 0;
};

class behaviorOne: public Strategy{
  private:
    void behave(){
        cout << "left strategy" << endl;
    }
};

class behaviorTwo: public Strategy{
  private:
    void behave(){
        cout << "right strategy" << endl;
    }
};

class behaviorThree: public Strategy{
  private:
    void behave(){
        cout << "center strategy" << endl;
    }
};

void TestBed::setBehavior(int type){  
  delete myStrategy;
  if (type == 0)
    myStrategy = new behaviorOne();
  else if (type == 1)
    myStrategy = new behaviorTwo();
  else if (type == 2)
    myStrategy = new behaviorThree();
}

int main(){
  TestBed test;
  int answer;  
  while(1){
     cout << "Exit(other) Left(0) Right(1) Center(2): ";
     cin >> answer;
     if(answer > 2) break;
     test.setBehavior(answer);
     test.myStrategy->performBehavior();
  }   
  return 0;
}