将Builder模式拉出到配置中的C ++模板问题?

时间:2013-10-03 17:16:49

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

我有一个算法需要大量参数(即配置)作为其构造函数的一部分,并且还需要一些明确定义的创建步骤。因此,我创建了一个Builder Pattern实现,允许设置所需的参数并创建中间和最终实例,例如。

// somewhere
class SomeAlgo { 
    public:
       SomeAlgo(double a, double b, double c, double d, double e /* etc */);
;

现在我将Builder定义为例如。

class SomeAlgoBuilder {
    public:
      SomeAlgo& createResult() { /* TODO: */ }

      virtual SomeAlgoBuilder& creationStep1() = 0;
      virtual SomeAlgoBuilder& creationStep2() = 0;
      virtual SomeAlgoBuilder& creationStep3() = 0;

      // example setter note the builder returns *this
      SomeAlgoBuilder& setA(double a) { a_ = a; return *this; } 
      SomeAlgoBuilder& setB(double b) { b_ = b; return *this; } 
      // etc 
};

此时一切看起来还不错,但现在我想Pull Up构建器的SomeAlgoConfig成为// not "is a" config but need the implementation inheritance // >>>>>> note the need to pass SomeAlgoBuilder as template class SomeAlgoBuilder : private SomeAlgoConfig<SomeAlgoBuilder> { public: SomeAlgo& createResult() { /* TODO: */ } virtual SomeAlgoBuilder& creationStep1() = 0; virtual SomeAlgoBuilder& creationStep2() = 0; virtual SomeAlgoBuilder& creationStep3() = 0; }; 类,这样我就可以覆盖传递简单配置的用例一个复杂的长参数列表。这种简单的配置在Java中被称为值对象或Bean。新的Builder将是这样的:

SomeAlgoConfig

现在template<T> class SomeAlgoConfig { T& setA(double a) { a_ = a; return *static_cast<T*>(this); } T& setB(double b) { b_ = b; return *static_cast<T*>(this); } // etc } 实施:

SomeAlgoConfig config; // <<< here it won't compile because it misses the T parameter
config.setA(a).setB(b).setC(c);

意图是这样使用的:

SomeAlgoConfig

这就是我猜的伎俩。但是,每当我想单独使用SomeAlgoConfig<SomeAlgoConfig>时(在Builder的上下文之外),例如要将它作为参数传递我需要使用模板参数声明它,该参数本身就是template<typename T = SomeAlgoConfig> class SomeAlgoConfig。如何以默认为模板类型的方式定义它?例如执行此操作不起作用:SomeAlgoConfig因为此时尚不知道{{1}}。

1 个答案:

答案 0 :(得分:1)

Config应该像参数的容器一样,因此每当您改变想要传递的参数时,就不必更改构造函数和setter。使构建器继承配置毫无意义,因为构建器不是配置,“我需要继承的方法”不是在您的设计中实现它的有效参数。您可以将配置作为构建器的成员并调用:

builder.getConfig().setA(a);
builder.getConfig().setB(b);
//...
builder.createResult();

如果您想要模板配置,您也可以制作构建器模板,例如:

template<class T>
class AlgoBuilder<T>{
//...
private:
AlgoConfig<T> config;

这样,您可以在构造函数中设置传递配置。

关于在实例化配置时遗漏T参数的问题......那么,既然你想设置a,b,c和所有其他参数,你已经知道了参数的类型,所以你实际上可以使用T类型实例化配置,这与您的参数类型相同。 AlgoConfig&LT; AlgoConfig&GT;对我没有多大意义。