传递大量参数的C ++设计模式

时间:2011-04-05 12:16:22

标签: c++ algorithm design-patterns function parameters

我有一个合理大小的类,它实现了几个与逻辑相关的算法(来自图论)。需要大约10-15个参数作为算法的输入。这些不是由算法修改的,而是用于指导它的操作。首先,我解释了实现这个的两个选项。我的问题是这样做的常用方法是什么(无论是否是两种选择之一)。

N很大时,我个人不喜欢将这些值作为参数传递给函数,特别是在我还在开发算法时。

void runAlgorithm(int param1, double param2, ..., bool paramN);

相反,我有一个包含算法的类Algorithm,我有一个包含这些参数的结构AlgorithmGlobals。我要么将这个结构传递给:

void runAlgorithm(AlgorithmGlobals const & globals);

或者我在类中添加一个公共AlgorithmGlobals实例:

class Algorithm {
public:
    AlgorithmGlobals globals;
    void runAlgorithm();
}

然后我在其他地方使用它:

int main() {
    Algorithm algorithm;
    algorithm.globals.param1 = 5;
    algorithm.globals.param2 = 7.3;
    ...
    algorithm.globals.paramN = 5;

    algorithm.runAlgorithm();

    return 0;
}

请注意AlgorithmGlobals的构造函数为每个参数定义了良好的默认值,因此只需要指定具有非默认值的参数。

AlgorithmGlobals不是私有的,因为可以在调用runAlgorithm()函数之前自由修改它们。没有必要“保护”它们。

6 个答案:

答案 0 :(得分:12)

这被称为"Parameter object" pattern,这通常是一件好事。我不喜欢会员版本,特别是称它为“XGlobals”并暗示它在各地共享。相反,参数对象模式通常涉及创建参数对象的实例并将其作为参数传递给函数调用。

答案 1 :(得分:8)

其他人提到参数对象,但还有另一种可能性:使用Builder

Builder允许您省略默认值适合的参数,从而简化代码。如果您要将算法与几组不同的参数一起使用,这将特别方便。 OTOH它还允许您重用类似的参数集(尽管存在无意重用的风险)。这(与方法链接一起)将允许您编写诸如

之类的代码
Algorithm.Builder builder;

Algorithm a1 = builder.withParam1(1).withParam3(18).withParam8(999).build();
...
Algorithm a2 = builder.withParam2(7).withParam5(298).withParam7(6).build();

答案 2 :(得分:6)

您应该在设计中提出几点不同的想法:

  1. 参数纯粹是输入。
  2. 参数特定于您的算法。
  3. 参数的默认值是合理的。

  4. class Algorithm {
      public:
        class Parameters { // Nested class, these are specific to your algorithm.
          public:
            Parameters() : values(sensible_default) { }
            type_t values; // This is all about the data.
        };
    
        Algorithm(const Parameters &params) : params_(params) { }
    
        void run();
    
      private:
        const Parameters params_; // Paramaeters don't change while algorithm
    };                            // is running. 
    

    这就是我的建议。

答案 3 :(得分:4)

我使用你已经提到的这种技术:

void runAlgorithm(AlgorithmGlobals const & globals);

但是会改为调用班级AlgorithmParams

答案 4 :(得分:4)

此处Named Parameter Idiom可能会有用。

a.runAlgorithm() = Parameters().directed(true).weight(17).frequency(123.45);

答案 5 :(得分:1)

建议为什么不这样做:

class Algorithm {
public:
Algorithm::Algorithm(AlgorithmGlobals const & globals) : globals_(globals) {}

    void runAlgorithm(); // use globals_ inside this function

   private:
    const AlgorithmGlobals globals_;
    };

现在你可以这样使用它:

AlgorithmGlobals myglobals;
myglobals.somevar = 12;

Algorithm algo(myglobals);
相关问题