Sé que tener variables globales o clases de singleton crea casos que pueden ser difíciles de probar / administrar y me he visto obligado a usar esos patrones en el código, pero a menudo tienes que enviarlos.
Entonces, ¿hay casos en que las variables globales o singletons sean realmente útiles en el desarrollo de juegos?
software-engineering
design-patterns
Ólafur Waage
fuente
fuente
Definitivamente una lista no exhaustiva, pero aquí va:
Contras
Ya sea a favor o en contra
Pros
Usamos mucho una "estructura de singletons globales" en nuestros títulos portátiles. Los títulos de PC y consola tienden a depender menos de ellos; cambiaremos más hacia una arquitectura de mensajería / dirigida por eventos. Dicho esto, los títulos de PC / consola todavía usan a menudo un TextureManager central; ya que generalmente envuelve un único recurso compartido (la memoria de textura), esto tiene sentido para nosotros.
Si mantiene su API relativamente limpia, puede que no sea demasiado difícil refactorizar (¡o usar!) Un patrón singleton cuando lo necesite ...
fuente
Pueden ser muy útiles, especialmente durante la creación de prototipos o la implementación experimental, pero en general preferimos pasar referencias para estructuras similares a las de los gerentes, de esa manera al menos tiene cierto control sobre desde dónde se accede. El mayor problema con los globales y los singletons (en mi opinión) es que no son muy compatibles con múltiples subprocesos, y el código que los usa es mucho más difícil de transportar a la memoria no compartida, como las SPU.
fuente
Yo diría que el diseño de singleton en sí mismo no es útil en absoluto. Definitivamente, las variables globales pueden ser útiles, pero prefiero verlas ocultas detrás de una interfaz bien escrita para que no sepa de su existencia. Con los singletons eres definitivamente consciente de su existencia.
A menudo uso variables globales para cosas que necesitan acceso a través de un motor. Mi herramienta de rendimiento es un buen ejemplo que utilizo en todo el motor para llamar. Las llamadas son simples; ProbeRegister (), ProbeHit () y ProbeScoped (). Su acceso real es un poco más complicado y utiliza variables globales para algunas de sus cosas.
fuente
El principal problema con los globales y los singletons mal implementados son los oscuros errores de construcción y deconstrucción.
Entonces, si trabaja con primitivas que no tienen estos problemas o son muy conscientes del problema con un puntero. Entonces se pueden usar de forma segura.
Los globales tienen su lugar, igual que los gotos y no deben descartarse sin más, sino que deben usarse con cuidado.
Hay una buena explicación en la Guía de estilo de Google C ++
fuente
Los globales son útiles al crear rápidamente prototipos de un sistema que requiere cierto estado entre las llamadas a funciones. Una vez que haya establecido que el sistema funciona, mueva el estado a una clase y convierta las funciones en métodos de esa clase.
Los Singletons son útiles para causar problemas a usted mismo y a los demás. Mientras más estado global introduzca, más problemas tendrá con la corrección del código, mantenimiento, extensibilidad, concurrencia, etc. Simplemente no lo haga.
fuente
Tiendo a recomendar el uso de algún tipo de contenedor DI / IoC con administración personalizada de por vida en lugar de singletons (incluso si usa un administrador de por vida de "instancia única"). Al menos, es fácil cambiar la implementación para facilitar las pruebas.
fuente
Si desea las funciones de ahorro de memoria de un singleton, ¿podría probar el patrón de diseño de peso mosca?
http://en.wikipedia.org/wiki/Flyweight_pattern
En lo que respecta a los problemas de subprocesos múltiples mencionados anteriormente, debería ser bastante simple con cierta previsión implementar un mecanismo de bloqueo para los recursos que pueden compartirse entre subprocesos. http://en.wikipedia.org/wiki/Read/write_lock_pattern
fuente
Los Singleton son una excelente manera de almacenar un estado compartido en un prototipo temprano.
No son una bala de plata y vienen con algunos problemas, pero son un patrón muy útil para ciertos estados de IU / Lógica.
Por ejemplo, en iOS, usas singletons para obtener la [UIApplication sharedApplication], en cocos2d puedes usarla para obtener referencias a ciertos objetos como [CCNotifications sharedManager] y, personalmente, generalmente comienzo con un singleton [Game sharedGame] donde puedo estado de tienda que se comparte entre muchos componentes diferentes.
fuente
Wow, esto es interesante para mí, ya que nunca he tenido un problema personal con el patrón singleton. Mi proyecto actual es un motor de juego C ++ para Nintendo DS, y estoy implementando muchas de las utilidades de acceso de hardware (es decir, VRAM Banks, Wifi, los dos motores gráficos) como instancias únicas, porque están destinadas a envolver C global funciones en la biblioteca subyacente.
fuente
Solo cuando tiene un elemento que solo tiene un controlador pero es manejado por varios módulos.
Como, por ejemplo, la interfaz del mouse. O interfaz de joystick. O reproductor de música. O reproductor de sonido. O la pantalla. O el administrador de guardar archivos.
fuente
¡Los globales son mucho más rápidos! Por lo tanto, encajaría perfectamente para una aplicación intensiva en rendimiento, como un juego.
Los Singletons son una mejor herramienta global, IMO y, por lo tanto, la herramienta correcta.
¡Úselo con moderación!
fuente