Estoy haciendo un juego en as3 usando flash desarrollo y flash cs5. Todo está orientado a objetos. Me preguntaba si debería tener una clase de "puerta de enlace" que tenga una referencia de propiedad a todas las instancias de otras clases, y simplemente paso esta clase de puerta de enlace a nuevos objetos, para que tengan acceso a cada clase. Al igual que:
var block:Block=newBlock(gateway);//In the block class:this.gateway.player.setHealth(100);//Or:this.gateway.input.lock();
¿Es esto como un patrón singleton o algo así? ¿Debo hacer esto?
Los objetos de contexto ayudan a la prueba, porque puede pasar contextos simulados a las funciones que desea probar. Los Singletons lo impiden, porque para burlarse de Singletons necesitas hacer que no sean Singletons.
Los objetos de contexto hacen que su "estado global" sea explícito y, por lo tanto, más fácil de razonar. Si una función no toma un objeto de contexto, sabe que no usa ningún estado de contexto global. No tiene tal garantía con singletons o variables globales.
Los objetos de contexto son un poco más lentos si no los usa, porque agrega otro parámetro a todas sus llamadas a funciones. Pueden ser más rápidos que los globales si los usa, y casi siempre son más rápidos que los singletons.
Los objetos de contexto son más fáciles de implementar; Por lo general, viven en el montón o en la pila de una manera normal. Los singleton tienen problemas complicados relacionados con el enhebrado en muchos idiomas.
Entonces no, este no es un singleton, es mucho mejor que un singleton.
Sin embargo, todavía está pasando una carga de estado: el hecho de que lo mantenga todo en una sola variable local lo hace más explícito, pero aún crea una gran confusión de preocupaciones . Tenga en cuenta la regla de responsabilidad única . Tiene sentido que haya un contexto que sea propietario del jugador y el nivel actual, están relacionados, pero ¿por qué el mismo contexto posee su entrada de teclado?
Considere diferentes niveles de contextos, por ejemplo:
GameplayContext: posee el jugador, los enemigos, la geometría de nivel, etc.
InputContext: posee controladores de teclado y mouse, eventos de entrada, etc.
GraphicsContext: posee texturas, el asa de la ventana, etc.
GlobalContext: posee GameplayContext, GraphicsContext y InputContext. Aquí es donde desea aplicar el patrón de localización de servicios , para poder intercambiar algunos contextos por otros según sea necesario. Y tal vez, para una iteración y prueba rápidas, esto debería estar en una variable global real: solo tenga en cuenta que cada vez que lo usa, está acumulando deuda tecnológica .
Estos contextos aún combinan inquietudes un tanto, tal vez algún controlador de eventos toma un GameplayContext y realmente solo necesita al jugador, pero las responsabilidades están claramente establecidas. Sabes que algo que requiere un GameplayContext no cargará una textura; algo que toma un InputContext no puede matar a un jugador.
+1 Buena respuesta. Sin embargo, algunas de las preocupaciones de velocidad o subprocesos no se aplican realmente en este contexto (ActionScript3 no admite subprocesos y muchos mecanismos de mejora de la velocidad que funcionan en C ++ no se aplican cuando se usa AS3).
bummzack
No sé mucho sobre el AS3VM, pero en la mayoría de los lenguajes dinámicos, el costo de pasar / recibir / usar un local es aún más rápido (búsqueda de matriz) que el costo de buscar un global (búsqueda hash), y mucho más rápido que llamando a una función (cargas de cosas) para llegar a ella. Así que creo que ese consejo aún se aplica.
0
Esto no se parece al patrón Singleton. Según tengo entendido, estás pasando un objeto con referencias a objetos de juego importantes a todas tus instancias.
Si este fuera el patrón Singleton, tendría:
AudioManager.getInstance().playSound(XY);
Mientras que en su caso podría tener:
this.gateway.getAudioManager().playSound(XY);
Se ve básicamente igual, pero realmente no lo es. Si desea reemplazar AudioManagercon una nueva (clase extendida) como ExtendedAudioManager, golpearía una pared usando el patrón Singleton. Sin embargo, su enfoque de puerta de enlace manejará eso bien.
El inconveniente de su enfoque es que tendrá que pasar por gatewaytodas partes. El patrón del localizador de servicios (propuesto por Joe Wreschnig en este hilo) parece un buen reemplazo para su "patrón de puerta de enlace".
Sin embargo, a veces es mejor simplemente ejecutar con el método simple y directo en lugar de sobrediseñar las cosas. Especialmente cuando es un proyecto pequeño o un prototipo. Tal vez podría hacer que sea gatewayuna especie de variable global ... por ejemplo. Game.gatewayy corre con eso.
La mayoría de las soluciones a este problema, incluido el patrón Singleton, implican el uso de variables estáticas. Si solo tiene un jugador, puede hacer que Player sea una clase única, lo que significa que puede acceder a la instancia de Player a través de algo como Player.currentPlayer. Sin embargo, muchas personas se enfurecen contra Singletons. También podría tener un ResourceManager o una clase similar que contenga referencias estáticas a varias variables globales útiles o bastante globales. En su código, también puede hacer que las variables de "Gateway" estén accesibles estáticamente en lugar de inflar su código pasándolo a todas partes.
La pregunta ha cambiado sustancialmente desde que hice esta respuesta, lo suficiente como para que no valga la pena editarla.
Gregory Avery-Weir
2
Aparte del título, nada cambió en la pregunta.
bummzack
1
¿Qué? Nada ha cambiado más que el título. -1
AttackingHobo
Creo que estaba pensando en el título aquí; Recuerdo que el título original era algo así como "¿Cómo debo hacer esto?" Es totalmente posible que haya leído mal el título / pregunta inicial cuando hice la respuesta.
Esto no se parece al patrón Singleton. Según tengo entendido, estás pasando un objeto con referencias a objetos de juego importantes a todas tus instancias.
Si este fuera el patrón Singleton, tendría:
Mientras que en su caso podría tener:
Se ve básicamente igual, pero realmente no lo es. Si desea reemplazar
AudioManager
con una nueva (clase extendida) comoExtendedAudioManager
, golpearía una pared usando el patrón Singleton. Sin embargo, su enfoque de puerta de enlace manejará eso bien.El inconveniente de su enfoque es que tendrá que pasar por
gateway
todas partes. El patrón del localizador de servicios (propuesto por Joe Wreschnig en este hilo) parece un buen reemplazo para su "patrón de puerta de enlace".Sin embargo, a veces es mejor simplemente ejecutar con el método simple y directo en lugar de sobrediseñar las cosas. Especialmente cuando es un proyecto pequeño o un prototipo. Tal vez podría hacer que sea
gateway
una especie de variable global ... por ejemplo.Game.gateway
y corre con eso.fuente
La mayoría de las soluciones a este problema, incluido el patrón Singleton, implican el uso de variables estáticas. Si solo tiene un jugador, puede hacer que Player sea una clase única, lo que significa que puede acceder a la instancia de Player a través de algo como Player.currentPlayer. Sin embargo, muchas personas se enfurecen contra Singletons. También podría tener un ResourceManager o una clase similar que contenga referencias estáticas a varias variables globales útiles o bastante globales. En su código, también puede hacer que las variables de "Gateway" estén accesibles estáticamente en lugar de inflar su código pasándolo a todas partes.
fuente