2013-10-03 65 views
0

我有一個算法,需要大量的參數(即配置)作爲其構造函數的一部分,也需要一些明確定義的創建步驟。因此,我創建了一個Builder Pattern實現,該實現允許設置所需參數並創建中間實例和最終實例,例如將Builder模式拉入配置的C++模板問題?

// 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 UpSomeAlgoConfig類,這樣我也可以覆蓋傳球,而不是一個令人費解的長圍繞一個簡單結構的用例參數列表。這個簡單的配置就是Java被稱爲Value Object或Bean的內容。新生成器會是這樣的:

// 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; 
}; 

現在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(在Builder的環境之外),例如把它作爲參數傳遞給我,我需要用一個模板參數來聲明它,它本身就是SomeAlgoConfig<SomeAlgoConfig>。我怎樣才能以默認自己爲模板類型的方式來定義它?例如這樣做不起作用:template<typename T = SomeAlgoConfig> class SomeAlgoConfig,因爲SomeAlgoConfig目前還不知道。

回答

1

Config應該像參數容器一樣,所以無論何時您改變想要傳遞的參數的想法,都不必更改構造函數和設置器。使構建器繼承配置沒有任何意義,因爲構建器不是一個配置,「我需要繼承的方法」不是在您的設計中實現此功能的有效參數。你可以用make config建設者中的一員,並呼籲:

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 < AlgoConfig>對我來說沒有多大意義。

+0

謝謝。這是我試圖收斂的地方,最小化參數改變時需要改變的地方的數量。我也發現你的解決方案非常乾淨和優雅。謝謝! –