2009-07-08 7 views
7

ここには、一般的で単純なタスクがあります:構成ファイルから構成設定を読み込み、オブジェクトに設定(ハッシュなど)を保存し、構成にアクセスする必要があるさまざまなオブジェクトからこのオブジェクトにアクセスしますパラメーター。グローバルパラメータオブジェクトを作成する方法

ConfigFileクラスの実装でthis implementationが見つかりました。私の質問は、このクラスのインスタンスを他のクラスから利用できるようにし、スレッドセーフで、静的な初期化順序の失敗などを避けるための最良の方法は何ですか?

私の現在のアプローチは、

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

、その後パラメータグローバル変数を作ります。しかし、グローバル変数の代わりにシングルトンを使うべきだということも読んでいます。シングルトンはどのようにしてファイル名でインスタンス化できますか?

これは一般的に受け入れられている良い方法でなければならないと思います。誰かが私にそれを指すことができるなら、私は感謝します。

おかげで、 C

答えて

6

ロールオーダーする場合は、設定クラスにシングルトンデザインパターンを使用することをおすすめします。 クラス自身が独自の型の静的ポインタを格納し、コンストラクタをプライベートにすることで、静的ゲッタを使用してクラスの1つのインスタンスを取得するよう強制されます。

ので、ここでモックアップは、(それが楽しいコンフィグ機能が欠落している、コンパイルされないかもしれないが、ポイントを説明する必要があります)

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()を呼び出して操作を呼び出すだけで済みます。標準グローバル変数よりもずっときれいです。

Blast - 私はこれを書いていた頃、他の人もシングルトンデザインパターンを提案しました。ああ、もう一つの説明が役立つことを願っています。

2

あなたがBoost's Program Options図書館で見たことがありますか?

+0

ブーストPOライブラリはコマンドラインプログラムオプションを扱いますが、私の質問はファイルから読み込む設定オプションに関するものでした。 – recipriversexclusion

+0

設定ファイルからそのライブラリを読むことができます。 –

2

私の設定クラスで行ったことは、ハッシュテーブルキャッシュを持つシングルトン静的クラスを作成することです。私の設定ファイルは、アプリケーションの設定を変更するために読み書きするように設計されています。

設定を取得する呼び出しが行われるたびに、ハッシュテーブルが見つからない場合はそのファイルから設定を読み込み、ハッシュテーブルをロックしてハッシュテーブルに配置します。ルックアップのためのハッシュテーブルは非常に高速です。

0

私はChrisに同意し、シングルトンを使用します。シングルトンパターンについての良い点は、最初にアクセスしようとするときに必要なデータを初期化/収集するだけです。興味のあるすべての人が利用できるようになります。設定を変更できるようにする場合は、ライターをロックする必要があります。

2

「静的初期化順序の大失敗」を言及することで、私はあなたには、いくつかの静的オブジェクトを初期化するために利用可能な設定項目を持っている必要がありますと仮定します。シングルトンのConfigFileクラスは動作しますが、main()を起動する前に情報が必要なので、ファイル名の取得方法を変更する必要があります。ファイル名を提供するために別のシングルトンが必要になるか、ファイル名を構成クラス自体に組み込む必要があります。

0

私はこのようなグローバルリソースを構成するためにシングルトンデザインパターンに似たテクニックを使用しました。それはそれが例外をスローしている場合

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_configInstancethisに設定して、構築を終了して登録します。

getConfig方法は、インスタンスを返すか、設定されていない場合、例外をスロー。

デストラクタは、m_configInstanceを再び0に設定します。

main()の開始に一度、それを構築するクラスを使用します。その後、必要に応じてgetConfig()メソッドでアクセスします。

Configオブジェクトの寿命がきれいにシングルトンとは異なり、制御されています。これは単体テストのための追加の利点を持っています。各テストまたは一連のテストは、それ自身のConfigオブジェクトを作成することができ、それらはすべてテストの間に素早くクリーンアップされます。

関連する問題