2009-07-08 60 views
7

以下是一個常見的簡單任務:從配置文件讀取配置設置,將設置(例如作爲散列)保存在對象中,從需要訪問配置的各種對象訪問此對象參數。如何創建全局參數對象

我發現this implementation爲ConfigFile類的實現,它的工作原理。我的問題是:什麼是使這個類的實例可以從我的其他類和線程安全,避免靜態初始化命令慘敗等最好的方法是什麼。

我目前的做法是在main()中構造它使用

// Read face detection related parameter values from the configuration file. 
string configFileName = "detection_parameters.txt"; 
try { 
    parameters = ConfigFile(configFileName); 
} 
catch(ConfigFile::file_not_found) { 
    cerr << "configuration file not found: " << configFileName << endl; 
    exit(-1); 
} 

,然後進行參數一個全局變量。但我也讀到應該使用單例而不是全局變量。單身人士如何用文件名實例化?

這一定是一個普遍的任務,我認爲必須有一個普遍接受的好辦法嗎?如果有人能指點我,我將不勝感激。

感謝, Ç

回答

6

如果你打算自己動手,我會建議在你的配置類中使用Singleton設計模式。 有沒有類本身存儲一個它自己的類型的靜態指針,並且構造函數是私有的,所以人們將被迫使用靜態獲取器來獲取類的一個實例。

這樣一個實體模型(即可能無法編譯,一個缺少樂趣配置功能,但應說明這一點)

class Config 
{ 
public: 
    static Config * getConfig(); 
    static void setConfigFileName(string filename); 
private: 
    Config(); 
    static string m_filename; 
    static Config * m_configInstance; 
}; 

在情況下,我沒有說清楚,了getconfig()將看看m_configInstance。如果它不是有效的,那麼它將創建一個(有權訪問私有構造函數)並將其存儲在m_configInstance中,以便每個後續調用都將訪問同一個調用。所以你的main()會使用setConfigFileName(),那麼任何類只需要調用Config :: getConfig(),然後調用它的操作。比標準的全局變量更清潔。

爆炸 - 在我寫這篇文章的時候,其他人也提出了單例設計模式。很好 - 希望額外的解釋有幫助。

2

我爲我的配置類所做的工作是創建一個帶有散列表緩存的單例靜態類。我的配置文件旨在讀取和寫入以更改應用程序設置。

無論何時調用拉設置,我都會對哈希表執行查找,如果哈希表不存在,那麼我從文件讀取設置,鎖定哈希表,並將其放入哈希表中。哈希表非常快速的查找。

0

我同意克里斯,使用單身。單身模式的好處在於,它只在你第一次嘗試訪問它時才初始化/收集你需要的數據,從那裏開始它對所有感興趣的人都是可用的。如果您打算允許更改配置,則需要鎖定作者。

2

通過提到「靜態初始化順序失敗」,我假設你需要有可用的配置項來初始化一些靜態對象。一個單獨的ConfigFile類可以工作,但是你必須改變你獲得文件名的方式,因爲在main()啓動之前需要這些信息。您需要另一個單例來提供文件名,或者將文件名構建到配置類本身中。

0

我已經使用了類似於singleton設計模式的技術來配置像這樣的全局資源。

class Config 
{ 
public: 
    Config(const string & filename) { 
     if (m_configInstance) { 
     throw AlreadyInitException; 
     } 
     // do main init 
     m_configInstance = this; 
    } 

    ~Config() { 
     m_configInstance = 0; 
    } 

    static Config * getConfig() { 
     if (!m_configInstance) { 
     throw NoConfigException; 
     } 
     return m_configInstance; 
    } 

private: 
    static Config * m_configInstance; 
}; 

Config * Config * m_configInstance = 0; 

構造測試,m_configInstance沒有設置,如果是它拋出一個異常。然後它通過將m_configInstance設置爲this來完成建立並註冊自己。

getConfig方法返回實例或拋出異常,如果它沒有設置。

析構函數將m_configInstance再次設置爲0。

要使用這個類構造它在main()的開始一次。然後在getConfig()方法需要時訪問它。

與單身人士不同,現在Config對象的生命週期得到了乾淨的控制。這爲單元測試帶來了額外的好處,每個測試或一組測試都可以創建自己的對象,並且在測試之間它們都被很好地清理乾淨。