Welches Muster ist das und soll ich es tun?


9

Ich mache ein Spiel in AS3 mit Flash Develop und Flash CS5. Alles ist objektorientiert. Ich habe mich gefragt, ob ich eine "Gateway" -Klasse haben soll, die einen Eigenschaftsverweis auf alle Instanziierungen anderer Klassen enthält, und ich übergebe diese Gateway-Klasse einfach an neue Objekte, damit sie Zugriff auf jede Klasse haben. Wie so:

 var block:Block = new Block(gateway);

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

Ist das wie ein Singleton-Muster oder so? Soll ich das machen

Antworten:


13

Dies wird als Kontextobjekt-Entwurfsmuster bezeichnet und ist besser als das Singleton-Muster.

  • Kontextobjekte unterstützen das Testen, da Sie Scheinkontexte an Funktionen übergeben können, die Sie testen möchten. Singletons behindern es, denn um Singletons zu verspotten, muss man sie nicht zu Singletons machen.
  • Kontextobjekte machen Ihren "globalen Status" explizit und daher leichter zu überlegen. Wenn eine Funktion kein Kontextobjekt akzeptiert, wissen Sie, dass sie keinen globalen Kontextstatus verwendet. Sie haben keine solche Garantie für Singletons oder globale Variablen.
  • Kontextobjekte sind etwas langsamer, wenn Sie sie nicht verwenden, da Sie allen Funktionsaufrufen einen weiteren Parameter hinzufügen. Sie können schneller als Globals sein, wenn Sie sie verwenden, und sind fast immer schneller als Singletons.
  • Kontextobjekte sind einfacher zu implementieren. Normalerweise leben sie auf normale Weise auf dem Haufen oder Stapel. Singletons haben knifflige Probleme beim Threading in vielen Sprachen.

Also nein, dies ist kein Singleton, es ist viel besser als ein Singleton.

Aber vorbei sind Sie immer noch ein crapload staatlicher um - die Tatsachebist du das alles in einem einzigen lokalen Variablenhalten macht es noch deutlicher, aber schafft noch große conflation von Bedenken . Beachten Sie die Regel der einen Verantwortung . Es ist sinnvoll, dass es einen Kontext gibt, dem der Player und das aktuelle Level gehören - sie sind verwandt -, aber warum besitzt derselbe Kontext Ihre Tastatureingabe?

Betrachten Sie verschiedene Kontextebenen, zum Beispiel:

  • GameplayContext - besitzt den Spieler, die Feinde, die Levelgeometrie usw.
  • InputContext - besitzt Tastatur- und Maushandles, Eingabeereignisse usw.
  • GraphicsContext - besitzt Texturen, das Fensterhandle usw.
  • GlobalContext - besitzt einen GameplayContext, einen GraphicsContext und einen InputContext. Hier möchten Sie das Service Locator-Muster anwenden , um bei Bedarf einige Kontexte gegen andere auszutauschen. Und für eine schnelle Iteration und Prüfung sollte dies möglicherweise eine echte globale Variable sein - stellen Sie einfach fest, dass Sie bei jeder Verwendung technische Schulden aufbauen .

Diese Kontexte bringen immer noch Bedenken zusammen - vielleicht nimmt ein Event-Handler einen GameplayContext und braucht wirklich nur den Spieler -, aber die Verantwortlichkeiten sind klar definiert. Sie wissen, dass etwas, das einen GameplayContext benötigt, keine Textur lädt. Etwas, das einen InputContext nimmt, kann einen Spieler nicht töten.


+1 Gute Antwort. Einige der Geschwindigkeits- oder Threadingprobleme betreffen in diesem Zusammenhang jedoch nicht wirklich (ActionScript3 unterstützt kein Threading und viele Mechanismen zur Geschwindigkeitsverbesserung, die in C ++ funktionieren, gelten bei Verwendung von AS3 nicht).
Bummzack

Ich weiß nicht viel über AS3VM, aber in den meisten dynamischen Sprachen sind die Kosten für das Übergeben / Empfangen / Verwenden eines lokalen Objekts immer noch schneller (Array-Suche) als die Kosten für das Nachschlagen eines globalen (Hash-Suche) und viel schneller als Aufruf einer Funktion (Craploads of Stuff), um darauf zuzugreifen. Daher denke ich, dass der Rat immer noch gilt.

0

Dies sieht nicht wie das Singleton-Muster aus. So wie ich es verstehe, übergeben Sie ein Objekt mit Verweisen auf wichtige Spielobjekte an alle Ihre Instanzen.

Wenn dies das Singleton-Muster wäre, hätten Sie:

AudioManager.getInstance().playSound(XY);

In Ihrem Fall könnten Sie:

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

Es sieht im Grunde gleich aus, ist es aber wirklich nicht. Wenn Sie durch AudioManagereine neue (erweiterte Klasse) wie ersetzen ExtendedAudioManagermöchten, schlagen Sie mit dem Singleton-Muster gegen eine Wand. Ihr Gateway-Ansatz wird dies jedoch problemlos bewältigen.

Der Nachteil Ihres Ansatzes ist, dass Sie gatewayüberall herumlaufen müssen. Das Service-Locator-Muster (von Joe Wreschnig in diesem Thread vorgeschlagen) scheint ein guter Ersatz für Ihr "Gateway-Muster" zu sein.

Manchmal ist es besser, einfach mit der einfachen und unkomplizierten Methode zu arbeiten, als Dinge zu überarbeiten. Besonders wenn es sich um ein kleines Projekt oder einen Prototyp handelt. Vielleicht könnten Sie das zu gatewayeiner Art globaler Variable machen. ZB. Game.gatewayund renn damit.


-2

Die meisten Lösungen für dieses Problem, einschließlich des Singleton-Musters, umfassen die Verwendung statischer Variablen. Wenn Sie immer nur einen Spieler haben, kann Player nur eine Singleton-Klasse sein, was bedeutet, dass Sie über Player.currentPlayer auf die Player-Instanz zugreifen können. Viele Menschen toben jedoch gegen Singletons. Sie könnten auch einen ResourceManager oder eine ähnliche Klasse haben, die statische Verweise auf verschiedene nützliche globale oder verdammt globale Variablen enthält. In Ihrem Code können Sie auch die Variablen von "Gateway" statisch zugänglich machen, anstatt Ihren Code aufzublasen, indem Sie ihn überall weitergeben.


Die Frage hat sich seit dieser Antwort erheblich geändert, so dass es sich nicht lohnt, sie zu bearbeiten.
Gregory Avery-Weir

2
Abgesehen vom Titel hat sich an der Frage nichts geändert.
Bummzack

1
Was? Außer dem Titel hat sich nichts geändert. -1
AttackingHobo

Ich glaube, ich habe hier an den Titel gedacht; Ich erinnere mich, dass der Originaltitel so etwas wie "Wie soll ich das machen?" Es ist durchaus möglich, dass ich den ursprünglichen Titel / die ursprüngliche Frage falsch verstanden habe, als ich die Antwort gegeben habe.
Gregory Avery-Weir
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.