使用c ++随机选择算法的良好实践

时间:2010-08-16 14:23:13

标签: c++ design-patterns random function-pointers

环境:
必须生成伪随机模式。有几种方法/或算法可用于创建不同的内容。所有算法都会生成一个字符列表(但可能是其他任何东西)......重要的是,它们都返回相同类型的值,并且需要相同类型的输入参数。

必须可以调用GetRandomPattern()方法,该方法每次调用时都会使用随机算法。

我的第一个方法是将每个算法放在它自己的函数中,并在每次调用GetRandompattern()时选择一个随机函数。但是我没有提出另一种选择它们的方式,而不是一个不切实际,丑陋且不灵活的转换案例陈述。

class PatternGenerator{
 public:
  list<char> GetRandomPattern();
 private:
  list<char>GeneratePatternA(foo bar);
  list<char>GeneratePatternB(foo bar);
  ........
  list<char>GeneratePatternX(foo bar);
}

每次调用 GetRandomPattern()方法时,选择随机GeneratePattern函数的好方法是什么?

或者整个班级的设计应该不同吗?

非常感谢

4 个答案:

答案 0 :(得分:9)

为每个算法创建一个单独的类,每个类都对一个生成器类进行子类化。将这些对象的实例放入列表中。随机选择一个并使用它!

更一般地说,如果你开始使用相同的签名创建几个替代方法,那么尖叫的东西“将我们带入兄弟课程”:)

<强>更新 在指针建议出现之后,无法抗拒为面向对象的解决方案争论更多

  • 想象一下,在某些时候你想要打印哪个方法创建了哪个随机的东西。使用对象,它很容易,只需添加“名称”方法或其他东西。如果你得到的只是一个指针,你想如何实现这个目标? (是的,用指针创建字典,嗯...)
  • 想象一下,你发现你有十种方法,其中五种只有参数不同。所以你写了五个函数“只是为了保持代码清除OOP垃圾”?或者您是否宁愿拥有一个恰好能够存储某些状态的函数(也称为对象?)
  • 我想说的是,这是一个针对某些OOP设计的教科书应用程序。以上几点只是试图充实一点,并争辩说,即使它现在适用于指针,它也不是未来的解决方案。并且你不应该害怕制作与读者交谈的代码(即你的未来,在四周左右)告诉那个人它正在做什么

答案 1 :(得分:5)

您可以创建一个函数指针数组。这避免了必须创建一大堆不同的类,尽管您仍然必须将函数指针分配给数组的元素。无论你怎么做,都会有很多重复的线条。在您的示例中,它位于GetRandomPattern方法中。在我的,它在PatternGenerator构造函数中。

#define FUNCTION_COUNT 24
typedef list<char>(*generatorFunc)(foo);

class PatternGenerator{
    public:
        PatternGenerator() {
            functions[0] = &GeneratePatternA;
            functions[1] = &GeneratePatternB;
            ...
            functions[24] = &GeneratePatternX;
        }
        list<char> GetRandomPattern() {
            foo bar = value;
            int funcToUse = rand()%FUNCTION_COUNT;
            functions[funcToUse](bar);
        }
    private:
        generatorFunc functions[FUNCTION_COUNT];
}

答案 2 :(得分:1)

避免类似开关编码的一种方法是使用策略设计模式。例如:

class IRandomPatternGenerator
{
public:
  virtual list<int> makePattern(foo bar);
};

class ARandomPatternGenerator : public IRandomPatternGenerator
{
public:
  virtual list<int> makePattern(foo bar)
  {
    ...    
  }
};

class BRandomPatternGenerator : public IRandomPatternGenerator
{
public:
  virtual list<int> makePattern(foo bar)
  {
    ...    
  }
};

然后,您可以根据RandomPatternGenerator实例的运行时类型选择特定算法。 (例如创建列表,如nicolas78建议)

答案 3 :(得分:1)

感谢您的所有好评。 我决定使用函数指针,主要是因为我以前不知道它们,它们似乎非常强大,它是一个了解它们的好机会,但也因为它节省了很多代码行。

如果我要使用Ruby / Java / C#,我已经决定建议的策略设计模式; - )

class PatternGenerator{
 typedef list<char>(PatternGenerator::*createPatternFunctionPtr);
public:
 PatternGenerator(){
  Initialize();
   }
 GetRandomPattern(){
  int randomMethod = (rand()%functionPointerVector.size());
  createPatternFunctionPtr randomFunction = functionPointerVector.at( randomMethod );
  list<char> pattern = (this->*randomFunction)();
  return pattern;
  }
private:
  void Initialize(){
   createPatternFunctionPtr methodA = &PatternGenerator::GeneratePatternA;
   createPatternFunctionPtr methodB = &PatternGenerator::GeneratePatternB;
   ...
   functionPointerVector.push_back( methodA );
   functionPointerVector.push_back( methodB );
   }
  list<char>GeneratePatternA(){
   ...}
  list<char>GeneratePatternB(){
   ...}
  vector< createPattern > functionPointerVector;

可读性并没有像设计模式解决方案那样糟糕,添加新算法很容易,指针算术被封装在一个类中,它可以防止内存泄漏,而且非常快速有效...... / p>