Tengo este código existente donde tienen una clase y un método de inicialización en esa clase. Se espera que una vez que se crea el objeto de la clase, necesiten llamar a initialize en él.
Motivo por el que existe el método de inicialización El objeto se crea temprano para tener un alcance global y luego se llama al método de inicialización más tarde después de cargar un archivo dll del que depende.
Problema con la inicialización La clase ahora tiene este bool isInitialized que debe verificarse en cada método antes de continuar y devuelve un error si no se inicializa. En pocas palabras, es un gran dolor.
Una posible solución Inicializar en el constructor. Tenga solo un puntero al objeto en el ámbito global. Cree el objeto real después de que se cargue el dll.
Problema con la solución anterior Cualquier persona que cree un objeto de esta clase debe saber que debe crearse solo después de cargar el archivo DLL o, de lo contrario, fallará.
¿Es esto aceptable?
call_once
en C ++ 11 . Los proyectos que aún no están en C ++ 11 deben estudiar cómo se implementa call_once en C ++ 11 (centrarse en qué problema resuelve y luego cómo), y luego volver a implementarlo en su sabor (obsoleto) de C ++. Necesita una primitiva de sincronización segura de subprocesos múltiples, cuyo estado debe inicializarse estáticamente (con un valor constante). Tenga en cuenta que los compiladores anteriores a C ++ 11 pueden tener otras idiosincrasias que deben satisfacerse.Respuestas:
Suena como un trabajo para un proxy virtual.
Puede crear un proxy virtual que contenga una referencia al objeto en cuestión. Si bien la DLL no está cargada, el Proxy podría ofrecer cierto comportamiento predeterminado a los clientes, una vez que se carga la DLL, el proxy simplemente reenviará todas las solicitudes al asunto real.
El proxy virtual será responsable de verificar la inicialización de la DLL y, en función de esto, decide si la solicitud debe delegarse en el asunto real.
Patrón de proxy en Wikipedia
¿Cómo te gusta esta idea?
fuente
No ocurre nada útil si la DLL aún no está cargada; El objeto solo genera un error. ¿Es un error fatal? ¿Cómo se maneja el error?
¿Su metodología de prueba garantiza que este error nunca ocurra en el producto terminado?
Parece un trabajo de prueba, no de diseño arquitectónico. No solo devuelva un error,
assert
eso nunca sucede.Arregle a cualquier cliente de la clase que actualmente detecte e ignore el error para no intentarlo y causarlo en primer lugar.
Un patrón multiproceso podría ser establecer una variable de condición compartida después de cargar la DLL, y hacer que el constructor del objeto espere (y bloquee otros hilos) hasta que se cargue la DLL.
fuente
Primero: evite los objetos globales como la plaga, a menos que su estado nunca cambie (configuración).
Ahora, si está atrapado con él, por cualquier razón, hay varios diseños que probablemente podrían ayudarlo.
Se me ocurrieron dos ideas:
Use una fachada para cargar la DLL. Solo se puede acceder al Objeto a través de la Fachada, la Fachada carga la DLL después de la creación y crea una instancia del Objeto al mismo tiempo.
Use un Proxy, pero del tipo inteligente;)
Permítanme dar más detalles sobre el segundo punto, ya que temo que la respuesta de @edalorzo pueda haberlos asustado:
Ahora solo tiene un cheque único.
Esto también se puede hacer a través de algún tipo de puntero inteligente:
Aquí solo reserva espacio para un puntero, inicialmente nulo, y solo cuando se carga la DLL realmente asignará el objeto. Todos los accesos anteriores deben generar una excepción (NullException: p?) O finalizar el programa (limpiamente).
fuente
Esta es una pregunta difícil. Siento que la arquitectura puede ayudar con el problema.
Según la evidencia, parece que .dll no se carga cuando se carga el programa. Casi suena como un complemento.
Una cosa que viene a la mente es que debe inicializar el .dll. El programador tiene que suponer que el objeto no volverá de manera confiable, de todos modos. Es posible que pueda aprovechar esto (
bool isObjectLoaded() { return isInitialized; }
), pero definitivamente obtendrá más informes de errores sobre sus comprobaciones.Estaba pensando en un singleton.
Si llama al singleton, debería devolver el objeto correcto si puede recuperar uno. Si no puede devolver el objeto correcto, debería obtener algún valor de error / nullptr / objeto base vacío. Sin embargo, esto no funcionaría si el objeto puede morir en ti.
Además, si necesita varias instancias del objeto, puede usar algo como una Fábrica en su lugar.
fuente