Ich weiß, dass globale Variablen oder Singleton-Klassen Fälle verursachen, die schwierig zu testen / zu verwalten sind, und ich bin mit der Verwendung dieser Muster im Code überfordert, aber oft muss man sie versenden.
Gibt es also Fälle, in denen globale Variablen oder Singletons bei der Spieleentwicklung tatsächlich nützlich sind?
software-engineering
design-patterns
Ólafur Waage
quelle
quelle
Auf jeden Fall eine nicht erschöpfende Liste, aber hier geht's:
Nachteile
Entweder für oder gegen
Vorteile
In unseren Handheld-Titeln verwenden wir häufig eine "Struktur globaler Singletons". PC- und Konsolentitel sind in der Regel weniger auf sie angewiesen. Wir werden mehr auf eine ereignisgesteuerte / Messaging-Architektur umsteigen. Trotzdem verwenden die PC- / Konsolentitel immer noch häufig einen zentralen TextureManager. Da es normalerweise eine einzelne gemeinsam genutzte Ressource (den Texturspeicher) umschließt, hat dies für uns Sinn gemacht.
Wenn Sie Ihre API relativ sauber halten, ist es möglicherweise nicht allzu schwierig, ein Singleton-Muster zu überarbeiten (oder in!), Wenn Sie ...
quelle
Sie können sehr nützlich sein, insbesondere während des Prototyping oder der experimentellen Implementierung. Im Allgemeinen bevorzugen wir es jedoch, Referenzen für Manager-ähnliche Strukturen weiterzugeben, damit Sie zumindest eine gewisse Kontrolle darüber haben, von wo aus auf sie zugegriffen wird. Das größte Problem bei Globals und Singletons (meiner Meinung nach) ist, dass sie nicht sehr multithreadfreundlich sind und dass Code, der sie verwendet, viel schwieriger auf nicht gemeinsam genutzten Speicher wie SPUs zu portieren ist.
quelle
Ich würde sagen, dass das Singleton-Design selbst überhaupt nicht nützlich ist. Globale Variablen können auf jeden Fall nützlich sein, aber ich würde sie lieber hinter einer gut geschriebenen Oberfläche verstecken, damit Sie sich ihrer Existenz nicht bewusst sind. Mit Singletons sind Sie sich ihrer Existenz definitiv bewusst.
Ich verwende oft globale Variablen für Dinge, auf die über eine Engine zugegriffen werden muss. Mein Performance-Tool ist ein gutes Beispiel, das ich überall in der Engine zum Aufrufen verwende. Die Anrufe sind einfach; ProbeRegister (), ProbeHit () und ProbeScoped (). Ihr wirklicher Zugriff ist etwas kniffliger und verwendet für einige ihrer Dinge globale Variablen.
quelle
Das Hauptproblem bei globalen und schlecht implementierten Singletons sind obskure Konstruktions- und Dekonstruktionsfehler.
Wenn Sie also mit Grundelementen arbeiten, die diese Probleme nicht haben oder sich des Problems mit einem Zeiger sehr bewusst sind. Dann können sie sicher verwendet werden.
Globals haben ihren Platz, genau wie gotos, und sollten nicht sofort entlassen werden, sondern mit Vorsicht verwendet werden.
Eine gute Erklärung dafür finden Sie im Google C ++ Style Guide
quelle
Globals sind nützlich, um schnell ein System zu prototypisieren, das einen gewissen Status zwischen Funktionsaufrufen erfordert. Wenn Sie festgestellt haben, dass das System funktioniert, verschieben Sie den Status in eine Klasse und machen Sie die Funktionen zu Methoden dieser Klasse.
Singletons sind nützlich, um sich selbst und anderen Probleme zu bereiten. Je mehr globaler Status Sie einführen, desto mehr Probleme treten bei der Codekorrektheit, Wartung, Erweiterbarkeit, Parallelität usw. auf. Tun Sie es einfach nicht.
quelle
Ich empfehle eher die Verwendung eines DI / IoC-Containers mit benutzerdefinierter Lebensdauerverwaltung anstelle von Singletons (selbst wenn Sie einen Lebenszeitmanager mit einer einzelnen Instanz verwenden). Zumindest ist es dann einfach, die Implementierung auszutauschen, um das Testen zu erleichtern.
quelle
Wenn Sie die speichersparenden Funktionen eines Singletons möchten, können Sie vielleicht das Flyweight-Entwurfsmuster ausprobieren?
http://en.wikipedia.org/wiki/Flyweight_pattern
In Bezug auf die oben genannten Multithread-Probleme sollte es ziemlich einfach sein, einen Sperrmechanismus für Ressourcen zu implementieren, die von Threads gemeinsam genutzt werden können. http://en.wikipedia.org/wiki/Read/write_lock_pattern
quelle
Singletons sind eine großartige Möglichkeit, einen gemeinsamen Zustand in einem frühen Prototyp zu speichern.
Sie sind keine Wunderwaffe und haben einige Probleme, sind jedoch ein sehr nützliches Muster für bestimmte UI / Logic-Zustände.
In iOS verwenden Sie beispielsweise Singletons, um die [UIApplication sharedApplication] abzurufen. In cocos2d können Sie damit Verweise auf bestimmte Objekte wie [CCNotifications sharedManager] abrufen, und ich persönlich beginne normalerweise mit einem Singleton [Game sharedGame], wo ich kann Speicherstatus, der von vielen verschiedenen Komponenten gemeinsam genutzt wird.
quelle
Wow, das ist interessant für mich, da ich persönlich nie ein Problem mit dem Singleton-Muster hatte. Mein aktuelles Projekt ist eine C ++ - Spiel-Engine für den Nintendo DS, und ich implementiere viele der Hardware-Zugriffsdienstprogramme (z. B. VRAM Banks, Wifi, die beiden Grafik-Engines) als Singleton-Instanzen, da sie das globale C umschließen sollen Funktionen in der zugrunde liegenden Bibliothek.
quelle
Nur wenn Sie ein Element haben, das nur einen Controller hat, aber von mehreren Modulen verarbeitet wird.
Wie zum Beispiel die Mausschnittstelle. Oder Joystick-Oberfläche. Oder Musik-Player. Oder Soundplayer. Oder der Bildschirm. Oder der Manager zum Speichern von Dateien.
quelle
Globals sind viel schneller! Es würde also perfekt für eine leistungsintensive Anwendung wie ein Spiel passen.
Singletons sind eine bessere globale IMO und somit das richtige Werkzeug.
Gehen Sie sparsam damit um!
quelle