2009-07-08 15 views
7

Ecco un compito semplice e comune: leggere le impostazioni di configurazione da un file di configurazione, salvare le impostazioni (ad esempio come hash) in un oggetto, accedere a questo oggetto da vari oggetti che devono accedere alla configurazione parametri.Come creare un oggetto Parametri globali

Ho trovato this implementation per l'implementazione della classe ConfigFile e funziona. La mia domanda è: qual è il modo migliore per rendere un'istanza di questa classe disponibile dalle mie altre classi ed essere thread-safe, evitare il fiasco di inizializzazione statica, ecc.

Il mio attuale approccio è di costruirlo in main() usando

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

e poi fare parametri una variabile globale. Ma ho anche letto che i singleton dovrebbero essere usati al posto delle variabili globali. Come si può istanziare il singleton con il nome del file?

Questo deve essere un compito così comune che penso ci debba essere un modo generalmente accettato di farlo? Apprezzerei se qualcuno potesse indicarmi.

Grazie, C

risposta

6

Se si desidera eseguire il roll-out, è consigliabile utilizzare il modello di progettazione Singleton per la classe di configurazione. Fare in modo che la classe stessa memorizzi un puntatore statico del proprio tipo e il costruttore sia privato, in modo che uno sia obbligato a utilizzare il getter statico per ottenere l'istanza della classe.

così un mock-up (che non può compilare, una manca il divertimento funzionalità di configurazione, ma dovrebbe illustrare il punto)

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

Nel caso in cui non sto essere chiari, il GetConfig() sarebbe guarda m_configInstance. Se non è valido, creerebbe uno (ha accesso al costruttore privato) e lo memorizzerà in m_configInstance in modo che ogni chiamata successiva acceda allo stesso.

Quindi il vostro main() userebbe setConfigFileName(), quindi qualsiasi classe dovrebbe semplicemente chiamare Config :: getConfig() e quindi chiamare le operazioni su di esso. Molto più pulito di una variabile globale standard.

Blast - nel tempo in cui ho trascorso la scrittura di questo, altre persone hanno suggerito il modello di design singleton troppo. Ah bene - spero che la spiegazione aggiuntiva aiuti.

2

Hai guardato Boost's Program Options biblioteca?

+0

La libreria boost PO gestisce le opzioni del programma da riga di comando, la mia domanda riguardava le opzioni di configurazione da leggere da un file. – recipriversexclusion

+0

È possibile leggere da un file di configurazione con quella libreria. –

2

Quello che ho fatto per la mia classe di configurazione è creare una classe statica singleton con una cache hashtable. Il mio file di configurazione è progettato per essere letto e scritto per modificare le impostazioni dell'applicazione.

Ogni volta che viene effettuata una chiamata per eseguire un'impostazione, eseguo una ricerca sulla tabella hash, se non è presente, quindi leggo l'impostazione dal file, blocca la tabella hash e la metto nella tabella hash. La tabella hash molto veloce per le ricerche.

0

Sono d'accordo con Chris, uso un singleton. La cosa bella del modello singleton è che inizializza solo/raccoglie i dati di cui hai bisogno la prima volta che provi ad accedervi, da lì in poi è disponibile per tutti quelli che sono interessati. Se si intende consentire la modifica della configurazione, è necessario bloccare lo scrittore.

2

Con la menzione del "fiasco di ordine di inizializzazione statico", presumo che sia necessario disporre di elementi di configurazione per inizializzare alcuni oggetti statici. Una classe ConfigFile singleton funzionerà, ma è necessario cambiare il modo in cui si ottiene il nome del file poiché le informazioni sono necessarie prima che main() venga avviato. Avrai bisogno di un altro singleton per fornire il nome del file, o creare il nome del file nella classe di configurazione stessa.

0

Ho utilizzato una tecnica simile al modello di progettazione singleton per configurare risorse globali come questa.

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; 

I test costruttore che m_configInstance non è impostata, se è viene generata un'eccezione. Quindi finisce la costruzione e si registra inserendo m_configInstance in this.

Il metodo getConfig restituisce l'istanza o genera ed eccezione se non è impostato.

Il distruttore imposta nuovamente m_configInstance su 0.

Per utilizzare la classe, creare una volta all'inizio di main(). Quindi accedervi quando richiesto dal metodo getConfig().

Ora la durata dell'oggetto Config è controllata in modo pulito, a differenza di un singleton. E questo ha un ulteriore vantaggio per i test unitari, ogni test o una serie di test può creare un proprio oggetto Config e sono tutti ben puliti tra i test.