如何用std :: function在C ++中实现策略模式

时间:2015-03-13 12:04:32

标签: c++ pointers c++11 strategy-pattern std-function

我喜欢在C ++中实现策略模式的最佳方式。到目前为止,我一直使用标准方式,其中上下文具有指向基本策略类的指针,如下所示:

 class AbstractStrategy{
 public:
     virtual void exec() = 0;
 }
 class ConcreteStrategyA{
 public:
     void exec();
 }
 class ConcreteStrategyB{
 public:
     void exec();
 }

 class Context{
 public:
     Context(AbstractStrategy* strategy):strategy_(strategy){}
     ~Context(){
          delete strategy;
       }
      void run(){
           strategy->exec();
      }
 private:
     AbstractStrategy* strategy_;

由于指向对象的指针可能导致不良行为,我一直在寻找一种更安全的方式来实现这种模式,我发现this question提出了std::function作为处理这种模式的更好方法。

有人可以更好地解释一下std::function的工作原理,也许还有战略模式的例子吗?

4 个答案:

答案 0 :(得分:10)

请注意,单方法对象与函数同构,策略只是单方法对象。

所以基本上,你摆脱了所有的课程,而你只需使用std::function<void()>

class Context {
public:
    template<typename F>
    explicit Context(F strategy) : strategy(std::move(strategy)) { }

    void run() { strategy(); }

private:
    std::function<void()> strategy;
};

然后你可以将任何callable传递给Context的构造函数:

Context ctx([] { std::cout << "Hello, world!\n"; });
ctx.run();

答案 1 :(得分:4)

对此主题herehere进行了一些讨论。我认为这取决于手头的具体情况。例如,你的策略只是一个简单的函数调用 - 我经常有策略模式,我的策略需要多种功能,只需要一个函数或函数就不能很好地处理。但是如果你确实只需要一个函数或函子,那么std::function是一种方便的方法,可以实现最大的灵活性,存储函数指针,lambdas或functor。可能存在性能问题,对于原始的boost实现,已经讨论了here

答案 2 :(得分:1)

研究райтфолд

的答案

基本上,你摆脱了所有的类,你只需使用std :: function。

这个通用函数允许你传递函数,lambda,仿函数和成员函数(使用std :: bind)

class Context {
public:
   explicit Context(std::function<void()> input) : strategy(input) { }

void run() { strategy(); }

private:
   std::function<void()> strategy;
};

然后你可以将任何callable传递给Context的构造函数:

Context ctx([] { std::cout << "Hello, world!\n"; });
ctx.run();

void sayHelloWorld(){
   std::cout << "Hello, world!\n";
}


int main(){
   Context ctx( sayHelloWorld );
   ctx.run();  
}

class SayHelloWorld{
   operator()(){std::cout << "Hello, world!\n";}
}

int main(){
   SayHelloWorld hello_world;
   Context ctx( hello_world );
   ctx.run();  
}

答案 3 :(得分:0)

这样的东西?

#include <functional>
#include <iostream>


typedef std::function<int(int)> Strategy;

void execute_strategy(Strategy strategy, int object) {
    std::cout << strategy(object) << std::endl;
};

int power2(int i) {
    return i*i;
};

int main() {
    execute_strategy(power2, 3);
}

我的意思是,策略模式是解决没有实际lambda的缺点。这已经解决了,所以你可以通过相应的函数。