2011-10-28 27 views
2

我記得在閱讀複雜對象配置的情況下閱讀了一段C++的構造函數習語。它特別有用,因爲它有助於爲一些令人討厭的概念啓用RAII,這些概念有太多(通常是衝突)選項的方式對象構造函數「設置」習慣用法

這是一個簡單的例子。假設你要爲Win32 API窗口編寫一個包裝類。要初始化窗口,您需要知道窗口樣式,擴展窗口樣式,初始窗口位置,初始窗口大小等。在窗口樣式中,許多選項衝突並且不能設置在一起。將所有這些方法放在Window類中是禁止的,並且阻止定義適當的類不變量。使用臨時對象對所有參數值進行分組可能有助於防止不可能的配置,併爲Window類定義好的不變量(例如,它始終保存有效的窗口句柄)。

class Settings 
{ 
    ::DWORD myBasicStyles;  // takes lots of different flags. 
    ::DWORD myExtentedStyles; // even more flags. 
    ::POINT myInitialLocation; 
    ::SIZE myInitialSize; 
    // lots more... 
public: 
    void setInitialPosition (int x, int y); 
    void setInitialSize (int top, int left); 
    void useSpecialBorder(); 
    // lots more... 
    void enableTransparency(); 
    // lots more... 
}; 

class Window 
{ 
    ::HWND handle; 
public: 
    // map settings unto the horrible list of many parameters expected 
    // by "CreateWindowEx()", then invoke it to allocate the resource. 
    Window (const Settings& settings); 
}; 

// calling code. 
int main() 
{ 
    Settings settings; 
    settings.setInitialPosition(0, 0); 
    settings.setInitialSize(500, 300); 
    settings.setInitiallyVisible(true); 
    Window window(settings); 
    // ... rest of application ... 
} 

但是,我找不到我讀這個的頁面,甚至找不到它的名稱。任何人都可以告訴我這是什麼,並可能鏈接到一個關於這個問題的好資源?

+0

我不知道這有一個名字。 –

+0

@AlexandreC。這不是我經常見到的名字。我只是在和同事討論這種模式,並不記得我聽到的那種叫做什麼。我想爲它命名。 –

+0

順便說一句,如何在一個世界中,你能夠在const對象上調用那些setter? –

回答

3

看起來像混合的東西。

Settings對象是使用Named Parameter Idiom創建的。儘管通常你會看到它返回一個對自身的引用,所以你可以鏈接它們。

struct Builder { 
    Builder &one(int val) { one_ = val_; return *this; } 
    Builder &two(int val) { two_ = val_; return *this; } 
    int one; 
    int two; 
}; 

void foo() { 
    Builder builder().one(1).two(2); 
} 

Settings被用來作爲一個Encapsulated Context Pattern。鏈接有點羅嗦。基本思想是,你只需將你的參數粘貼到一個對象中並傳遞該對象。

在一個有點相關的whinge上,我發現它封裝了任何東西的想法是冒犯的。儘管如此,這可能只是人們超負荷詞彙的含義。 :)

+0

確實,它離建築商很近。我只是想避免使用術語「構建器」,因爲我們使用常規構造函數,而構建器不是「構建」任何東西。 –

+0

再看一遍,C++ FAQ中的鏈接是我真正想要的。很好找,謝謝。 –

1

我在互聯網上找到了名稱Named Parameter Idiom。它略有不同,但服務於相同的目的。

+0

這正是我正在尋找的鏈接。謝謝一堆。這與我記得的有點不同,但這正是我所尋找的。 –

+0

對不起,我在鏈接中混淆了。這是正確的名字,但是Tom Kerr鏈接到的C++ FAQ的描述就是我正在尋找的那個。 –

0

我寧可叫它參數對象成語如果你真的想要一個名字。與其背後的想法相比,這個名字其實並不重要。

這個想法是將一組相關數據與一個攜帶所有這些數據的對象組合在一起。將這些參數轉化爲對象是值得的,因爲:

  • 它減小了參數列表的大小,而長參數列表很難理解。
  • 新對象上定義的訪問器也使代碼更加一致,這又使它更易於理解。
  • 更重要的是,它可以幫助您識別這組數據上的這些常見行爲,以便您可以進入新班級。通過將這些行爲移動到新對象中,您可以識別重複的代碼並將其刪除。此外,你對數據有很好的封裝。一旦數據的任何操作的實施發生改變,只有一個地方可以改變,客戶端不會受到影響。
+0

其實名*很重要。我不需要解釋它,我可以指向[C++ FAQ項目10.20](http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.20)並讓人們閱讀說明。從那時起,我們可以使用術語「命名參數習語」來指代這個概念。 –

+0

只有當大多數人知道這個名字時,名字纔是重要的。) –

+0

工作在:-) –

相關問題