State-Pattern in AS3.0
Ich möchte euch hier das State-Pattern näher bringen und es gleich auch anhand eines AS3.0 Beispieles praktisch erklären.
Das State-Pattern ist ein “behavioural Pattern”. Das bedeutet es regelt den Ablauf, bzw. kann den Ablauf / das Verhalten für unsere Anwendung steuern. Wann immer wir sogenanntes zustandsbedinges, komplexeres Verhalten haben, sprich eine Anwendung z.B. auf selben KeyUp-Event ander Reagieren soll, je nachedem wo ich mich gerade befinde kann das State-Pattern in Punkto sauberer Programmierung uns wahrhaftig unterstützen. Die Vorstufe für das State-Pattern ist eine Zustandssteuerung durch Fallunterscheidung - sprich durch verschlungene If… else… Konstrukte. Man setzt mehrere Flags und guckt dann, wie man reagiert. Das Problem hierbei ist einerseitz die Übersichtlichkeit, andererseits die Wartbarkeit (guckt euch so ne 3-Seiten lange If-Else-Abfrage mal nach einem Jahr an und versucht zu verstehen, wann ihr in welchen Fall gelangt… ).
Vorteile auf einen Blick:
- einfache Strukturierung komplexem Verhaltens
- Übersichtlichkeit durch Aufteilung in mehrere Klassen
- Verbesserte Wartbarkeit auch nach längerer Projekt-Abstinenz
- Hinzufügen eines neuen Zustandes ist super-einfach (nur neue Klasse schreiben)
Die Kehrseite der Medallie:
- es entstehen mehr Klassen
- hinzufügen einer neuen Methode bedeutet overhead (alle States updaten)
So, nun zur Lösung des Problems: Wer hätte das gedacht - hier taugt das Statepattern!!! Hier erzeugt man nun für jeden Status, indem sich das Programm befinden kann eine seperate Klasse. In diesen sind die einzelnen Codefragmente (die sind zwischen If-Else-Blöcken stehen würden) in die verschiedenen Klassen ausgelagert. Dies steigert die Lesbarkeit eures Codes und die Findbarkeit von Fehlern.

Hier einmal der Grundaufbau, wie das Pattern strukturiert ist. Zum einen Gibt es die Klasse ClassX, die unsere Applikation darstellt. Diese wiederum hat ein Attribut “state”, welches vom Typ State ist und immer den aktuellen Zustand des Programmes repräsentiert. Die wahre Klasse “State” ist jedoch nur abstakt, von ihr können also keine direkten Instanzen erzeugt werden. Sie dient jedoch als Schablone für die weiteren State-Klassen, die von ihr erben (StateA, StateB,…. StateX). Das Prinzip ist nun folgendes. Im ersten Schritt muss die KlasseX beim initalisieren in einen Start-Zustand versetzt werden, z.B. this.state = new StateA();. Nun wird, ggf. op1 auf der aktuellen state instanz getriggert, was wiederum in unserem Beispiel zu Beginn die op1() von der Klasse StateA ist. Wenn diese Operation den Zustand nicht ändert gibt sie einfach wieder StateA zurück. Sollte sie den Zustand wechseln wollen gibt die Methode einfach ein neues Zustandsobjekt, beispielsweise new StateB() zurück. Damit befindet sich ClassX nun im Zustand B, ohne das diese irgendwas damit zu tun hatte, oder dies auch nur mitbekommen hat. ihr ist das total ega. Sie triggert einfach nur Methoden an ihren State. Was die dann zur Laufzeit damit machen, das ist ihnen überlassen und steht NUR ind den States selbst. => die Komplexität wird also aus der KlasseX ausgelagert und übersichtlich in die verschiedenen Status-Klassen verteilt.
Beispiel:
So, wem das noch zu komplex und zu Abstrakt war, hier ein Beispiel, wie das ganze in der Realität aussehen könnte. Nebem wir ein kleines Jump`n Run Game. Hier Haben wir meist eine Keyboard- oder Joystick-Steuerung, die je nachdem in welchem Modus die Figur sich gerade befindet verschieden Reagiert. Sprich: Befindet sich der Character auf festem Boden kann er rennen. Ist er gerade im Wasser kann er schwimmen. Befindet er sich im super-speed-Modus kann er super-schnell rennen etc…. Eurer Fantasie wie immer auch hier keine Grenzen gesetzt. So das ganze nun im State-Pattern gesprochen: Wir haben ein Game. Diese kann sich in mehreren Zuständen befinden. Der Einfachkeit halber habe ich mir mal 3 Modi ausgedacht: RunState, SwimState und PauseState. Je nachdem in welchem Modus der Anwender sich befindet hat das drücken z.B. der Pfeiltasten andere Funktionalität (im Pause-Modus z.B. kann der Anwender nichts drücken, ausser wieder “P” um die Pause aufzuheben).

Oben im Bild das ganze mal grafisch darsgestellt, wie das Pattern in der konkreten Ausprägung für das Game aussieht. Wir haben also eine Klasse Game, die z.B. die GUI initialisiert etc… Diese wiederum hat ein Attribut “state” vom Typ State. Die Klasse State ist übrigens in unserem Fall nicht abstrakt, denn das gibts ja in AS3.0 nicht, ist aber
Download:
Hier der Beispiel-Code zum Download
(Ach ja, das ist kein fertiges Spiel, sondern nur Traces, die das Ganze als Ausgabe simulieren)
Initialisierungs-Code:
Zum Initialisieren des Beispielcodes braucht ihr folgenden Zeilen:
------------------------ this.addChild(g);
g.startGame();
-----------------------
- Viel Spass damit!
September 25th, 2008 at 07:30
good site szcpiy
November 24th, 2008 at 23:55
[…] (hierzu gibt es eine Flex Komponente - für die Programmierung vielleicht auch meinen Beitrag zum State-Pattern ansehen, der sollte hierzu auch sehr nützlich sein..). Damit kann die Seite in bestimmten […]