Che modello è questo e dovrei farlo?


9

Sto realizzando un gioco in AS3 usando Flash Develop e Flash CS5. Tutto è orientato agli oggetti. Mi chiedevo, dovrei avere una classe "gateway" che ha un riferimento di proprietà a tutte le istanze di altre classi, e ho appena passato questa classe gateway a nuovi oggetti, in modo che abbiano accesso a ogni classe. Così:

 var block:Block = new Block(gateway);

 //In the block class:
 this.gateway.player.setHealth(100);
 //Or:
 this.gateway.input.lock();

È come un modello singleton o qualcosa del genere? Dovrei farlo?

Risposte:


13

Questo è chiamato modello di progettazione dell'oggetto di contesto ed è migliore del modello singleton.

  • Gli oggetti di contesto aiutano il test, poiché è possibile passare contesti fittizi alle funzioni che si desidera verificare. I singleton lo ostacolano, perché per deridere i singleton devi renderli non singleton.
  • Gli oggetti contestuali rendono esplicito il tuo "stato globale" e quindi più facile da ragionare. Se una funzione non accetta un oggetto di contesto, sai che non utilizza alcuno stato di contesto globale. Non hai tale garanzia con singoli o variabili globali.
  • Gli oggetti di contesto sono leggermente più lenti se non li si utilizza, poiché si aggiunge un altro parametro a tutte le chiamate di funzione. Possono essere più veloci dei globi se li usi e sono quasi sempre più veloci dei singoli.
  • Gli oggetti di contesto sono più facili da implementare; di solito vivono nell'heap o nello stack in modo normale. I singoli hanno problemi difficili che coinvolgono il threading in molte lingue.

Quindi no, questo non è un singleton, è molto meglio di un singleton.

Tuttavia, stai ancora attraversando un crapload di stato - il fatto che lo mantenga tutto in una singola variabile locale lo rende più esplicito, ma crea comunque una forte confusione di preoccupazioni . Tieni presente la regola dell'unica responsabilità . Ha senso che ci sia un contesto che possiede il giocatore e il livello attuale - sono correlati - ma perché lo stesso contesto possiede l'input da tastiera?

Considera diversi livelli di contesti, ad esempio:

  • GameplayContext: possiede il giocatore, i nemici, la geometria del livello, ecc.
  • InputContext: possiede handle di tastiera e mouse, eventi di input, ecc.
  • GraphicsContext: possiede le trame, la maniglia della finestra, ecc.
  • GlobalContext: possiede GameplayContext, GraphicsContext e InputContext. Qui è dove si desidera applicare il modello di localizzazione del servizio , per essere in grado di scambiare alcuni contesti con altri, se necessario. E forse, per una rapida iterazione e test, questo dovrebbe essere in una vera variabile globale - renditi conto che ogni volta che lo usi, stai accumulando debito tecnologico .

Questi contesti confondono ancora le preoccupazioni - forse alcuni gestori di eventi prendono un GameplayContext e hanno davvero bisogno solo del giocatore - ma le responsabilità sono chiaramente definite. Sai che qualcosa che prende un GameplayContext non caricherà una trama; qualcosa che prende un InputContext non può uccidere un giocatore.


+1 Buona risposta. Tuttavia, alcune delle preoccupazioni relative alla velocità o al threading non si applicano in questo contesto (ActionScript3 non supporta il threading e molti meccanismi di miglioramento della velocità che funzionano in C ++ non si applicano quando si utilizza AS3).
Bummzack,

Non so molto su AS3VM, ma nella maggior parte dei linguaggi dinamici, il costo del passaggio / ricezione / utilizzo di un locale è ancora più veloce (ricerca di array) rispetto al costo di ricerca di un globale (ricerca di hash) e molto più veloce di chiamando una funzione (crapload di roba) per ottenerla. Quindi penso che il consiglio sia ancora valido.

0

Questo non sembra il modello Singleton. Per come lo capisco, stai passando un oggetto con riferimenti a importanti oggetti di gioco a tutte le tue istanze.

Se questo fosse lo schema Singleton, avresti:

AudioManager.getInstance().playSound(XY);

Mentre nel tuo caso potresti avere:

this.gateway.getAudioManager().playSound(XY);

Sembra praticamente lo stesso, ma in realtà non lo è. Se si desidera sostituire AudioManagercon un nuovo (classe estesa) come ExtendedAudioManager, si dovrebbe colpire un muro utilizzando il modello Singleton. Il tuo approccio gateway lo gestirà bene.

Lo svantaggio del tuo approccio è che dovrai passare gatewayovunque. Il modello di localizzazione di servizio (proposto da Joe Wreschnig in questo thread), sembra un buon sostituto per il "modello di gateway".

A volte è meglio eseguire semplicemente con il metodo semplice e diretto invece di progettare troppo le cose. Soprattutto quando si tratta di un piccolo progetto o di un prototipo. Forse potresti creare gatewayuna sorta di variabile globale ... ad es. Game.gatewaye corri con esso.


-2

La maggior parte delle soluzioni a questo problema, incluso il modello Singleton, prevede l'uso di variabili statiche. Se avrai mai un solo giocatore, puoi semplicemente avere Player come una classe singleton, il che significa che potresti accedere all'istanza Player attraverso qualcosa come Player.currentPlayer. Molte persone si arrabbiano contro Singletons, tuttavia. Potresti anche avere un ResourceManager o una classe simile che contiene riferimenti statici a varie utili variabili globali o piuttosto dannate. Nel tuo codice, potresti anche rendere staticamente accessibili le variabili "Gateway" invece di gonfiare il tuo codice facendolo passare ovunque.


La domanda è cambiata sostanzialmente da quando ho fatto questa risposta, abbastanza da non sembrare valsa la pena modificarla.
Gregory Avery-Weir,

2
A parte il titolo, non è cambiato nulla nella domanda.
bummzack,

1
Che cosa? Nulla è cambiato tranne il titolo. -1
AttackingHobo

Penso che stavo pensando al titolo qui; Ricordo che il titolo originale era qualcosa del tipo "Come dovrei farlo?" È del tutto possibile che ho letto male il titolo / la domanda iniziale quando ho fatto la risposta.
Gregory Avery-Weir,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.