Singleton è la strada giusta da seguire nel caso di un gioco?

1

Ho letto i post più importanti di Stackoverflow e SE e in tutto il sito si dice quanto siano brutti i singleton, ma non sono sicuro di come riscrivere il mio codice.

A partire da ora ho due progetti che si legano a un gameEngine che ognuno ha una classe singleton per accedere al contenuto:

  • Singleton per recuperare / creare un'istanza di una griglia spaziale 3d e archiviarla come istanza attiva. Futher consente di iniettare propri tipi di dati conformi a un'interfaccia e quindi può essere de / -serializzato con attributi personalizzati in quell'istanza attiva. Aggiunta e rimozione di oggetti dall'istanza attiva e metodi collettivi per la stessa cosa.

  • Singleton per il ciclo AI principale: Aggiunta / rimozione di unità dal ciclo AI principale, Iniezione / sostituzione delle aggiunte alle principali StateMachineProcesses che pilotano l'intelligenza artificiale. Più significativo, quello che odio di questo secondo: Ha bisogno di accedere all'istanza della griglia attiva da Singleton # 1 come uno degli aspetti principali dell'IA è la consapevolezza di ciò che lo circonda e tutti gli oggetti del mondo sono memorizzati nel database del progetto numero uno .

Come dovrebbe esserci sempre solo un'istanza attiva di queste due cose, i singleton sono un'eccezione o c'è un modo migliore per ridisegnare l'intera cosa?

    
posta user3488765 09.12.2016 - 10:25
fonte

2 risposte

5

Is singleton the right way to go...

No. Un singleton a livello globale, accessibile a livello globale (ovvero il modello di progettazione singleton) è sempre un antipattern e c'è sempre un modo migliore di fare le cose.

Il modo standard per evitare questi singleton consiste nell'utilizzare l'iniezione di dipendenza (DI). Potresti ancora avere singole istanze di determinati oggetti, basta passarli a ciascun oggetto, anziché renderli accessibili a livello globale.

Nel tuo caso, potresti semplicemente passare a DI molto semplice passando la griglia spaziale 3d e i loop AI a tutti gli altri oggetti tramite i loro costruttori. Questo è grezzo, ma funziona intorno alla necessità di singleton e quindi, ad esempio, miglioreremo immediatamente la facilità con cui è possibile testare il codice.

    
risposta data 09.12.2016 - 10:33
fonte
-1

Ci sono alcune cose qui.

In primo luogo, se si dispone di un componente pesante risorsa che è necessario solo uno (o un numero limitato) di, allora un modello Singleton è perfettamente sensato. Come descritto, i tuoi due usi sembrano buoni candidati per singleton.

Nota, non è lo stesso che dire che dovrebbero essere globali. Questa è una domanda diversa (che verrò a). Potrebbe essere sensato, ad esempio, avere una griglia 3d singleton e passarla esplicitamente al loop AI del singleton.

Avere globals è generalmente una cattiva idea, o più specificamente avere globals mutabili è una cattiva idea. Poiché entrambi i componenti sono chiaramente mutabili, ciò influenzerebbe tale decisione. Non entrerò nei dettagli sul perché i globali sono cattivi in quanto non c'è carenza di commenti sulla 'rete su questo argomento.

Tuttavia, ciò che non viene spesso riportato è il motivo per cui si potrebbe desiderare di avere globali mutabili nonostante i loro aspetti negativi importanti.

Se non si dispone di globals, è necessario passare un riferimento all'oggetto a ogni funzione / metodo che deve accedervi. Evidentemente, questo occupa una discussione. In alcuni linguaggi ABI (in particolare alcuni C e C ++), i primi argomenti possono essere passati nei registri. Ora se si contano i cicli, ad esempio se si hanno vincoli di prestazione molto stretti, questo potrebbe essere un problema. Potresti passare continuamente un numero di riferimenti a un numero di funzioni molto usate causando perdite di registro regolari e errori di cache eccessivi.

Questa è mai una ragione sufficiente? Sì, può essere anche se nella mia esperienza è abbastanza raro. È interessante notare che il caso più comune che ho visto è nei motori di gioco in cui i singleton grandi e le caratteristiche di performance strette sono endemiche.

Dovresti usare le globali? Bene, questo ovviamente dipende dal dettaglio. Nella maggior parte dei casi, consiglierei di non farlo. Anche se hai bisogno di un globale, non trattarlo come se non fosse necessario. In altre parole, passalo alle funzioni che lo usano come argomento, tranne quando i requisiti di prestazione richiedono diversamente. Quindi documenta l'inferno.

Come per molte altre cose nel mondo del software, ci sono regole pratiche per i singleton e le globali, ma un buon ingegnere sa quando piegarle.

    
risposta data 09.12.2016 - 17:54
fonte