2009-07-08 12 views
7

Aquí hay una tarea común: leer los parámetros de configuración de un archivo de configuración, guardar los ajustes (por ejemplo, un hash) en un objeto, acceder a este objeto desde varios objetos que necesitan acceder a la configuración parámetros.Cómo crear un objeto de parámetros globales

Encontré this implementation para la implementación de la clase ConfigFile y funciona. Mi pregunta es: ¿cuál es la mejor manera de hacer que una instancia de esta clase esté disponible en mis otras clases y sea segura, evite el fiasco de orden de inicialización estática, etc.

Mi enfoque actual es construirlo en 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); 
} 

y luego hacer parámetros una variable global. Pero también leí que deberían usarse singletons en lugar de variables globales. ¿Cómo se puede crear una instancia del singleton con el nombre del archivo?

¿Esta debe ser una tarea tan común que creo que debe haber una buena forma generalmente aceptada de hacerlo? Agradecería que alguien me lo señale.

Gracias, C

Respuesta

6

Si va a rodar por su cuenta, le recomendaría usar el patrón de diseño de Singleton para su clase de configuración. Haga que la clase en sí almacene un puntero estático de su propio tipo, y el constructor sea privado, por lo que uno se verá forzado a usar el captador estático para obtener la única instancia de la clase.

así una maqueta (que pueden no recopilar, una falta la funcionalidad de configuración de diversión, sino que debe ilustrar este punto)

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

En caso de que no estoy siendo claro, la getConfig() haría mira m_configInstance. Si no es válido, entonces creará uno (tiene acceso al constructor privado) y lo almacenará en m_configInstance para que cada llamada subsiguiente acceda al mismo.

Así que su main() usaría setConfigFileName(), entonces cualquier clase solo tendría que llamar a Config :: getConfig() y luego llamar a las operaciones en él. Mucho más limpio que una variable global estándar.

Explosión: en el tiempo que he dedicado a escribir esto, otras personas me han sugerido también el patrón de diseño singleton. Ah bien - espero que la explicación adicional ayude.

2

¿Has mirado en Boost's Program Options biblioteca?

+0

La biblioteca PO de impulso maneja las opciones del programa de línea de comando, mi pregunta era acerca de las opciones de configuración para leer desde un archivo. – recipriversexclusion

+0

Puede leer desde un archivo de configuración con esa biblioteca. –

2

Lo que he hecho para mi clase de configuración es crear una clase estática singleton con una memoria caché hashtable. Mi archivo de configuración está diseñado para leerse y escribirse para cambiar la configuración de la aplicación.

Cada vez que se realiza una llamada para extraer una configuración, realizo una búsqueda en la tabla hash, si no está allí, luego leo la configuración del archivo, bloqueo la tabla hash y la coloco en la tabla hash. La tabla hash muy rápida para búsquedas.

0

Estoy de acuerdo con Chris, use un singleton. Lo bueno del patrón singleton es que solo inicializa/recopila los datos que necesita la primera vez que intenta acceder, a partir de ese momento está disponible para todos los interesados. Si va a permitir que la configuración cambie, querrá bloquear el escritor.

2

Al mencionar el "fiasco de orden de inicialización estática", supongo que debe tener elementos de configuración disponibles para inicializar algunos objetos estáticos. Una clase SingleNet ConfigFile funcionará, pero debe cambiar la forma en que obtiene el nombre del archivo, ya que la información es necesaria antes de que se inicie main(). Necesitará otro singleton para proporcionar el nombre de archivo, o construir el nombre de archivo en la clase de configuración en sí.

0

He utilizado una técnica similar al patrón de diseño singleton para configurar recursos globales como este.

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; 

Las pruebas constructor que m_configInstance no está ajustado, si es que se produce una excepción. Luego termina la construcción y se registra configurando m_configInstance en this.

El método getConfig devuelve la instancia o arroja una excepción si no está configurada.

El destructor establece el m_configInstance en 0 nuevamente.

Para usar la clase, contruya una vez en el inicio de main(). Luego acceda a él cuando lo requiera el método getConfig().

Ahora la vida útil del objeto Config está limpiamente controlada, a diferencia de un singleton. Y esto tiene un beneficio adicional para las pruebas unitarias, cada prueba o conjunto de pruebas puede crear su propio objeto Config y todas están bien limpiadas entre pruebas.

Cuestiones relacionadas