Ich arbeite gerade an einem Toolset für grafische Werkzeuge. Also Pinsel, Stifte usw.
Deren Verhalten soll nun durch einen "Zustandsautomaten" abgebildet werden. Die "" deshalb, weil es kein der Theorie nach korrekter Automat sein muss, sondern letztlich darum geht, das Verhalten einigermaßen zu sortieren.
Im Prinzip stehe ich da jetzt vor der Variante eine Zustandsklasse zu verwenden, deren eval() Funktion die aktuelle Situation auf dem Zeichenbrett verarbeitet und einen Folgezustand zurückgibt. (kann auch wieder der aktuelle Zustand sein)
Das funktioniert auch, ist aber ziemlich "dreckig", weil man von Außen gar nicht mehr weiß, wie der Automat aufgebaut ist. Eigentlich ist das mehr eine Art Token-Passing.
Einfaches Beispiel:
Z0: Maus drücken -> Z1 + "nichts machen"
Z1: Maus mehr als X bewegen -> Z2 + "Linie beginnen"
Z1: Maus innerhalb von Y ms anheben -> Z0 + "Blinksignal am Cursor Zeichnen"
Z1: Maus nach Y ms anheben -> Z0 + "nichts machen"
Z2: Maus bewegen -> Z2 + "Linie fortsetzen"
Z2: Maus anheben -> Z0 + "Linie beenden"
Das sind in etwa die logischen Zustände aus einem noch ziemlich einfachen Beispiel.
Die primitive Variante macht daraus 3 Zustände, deren eval() Funktionen dann aber nicht komplett statisch sind (lässt sich mit externen Properties verbessern) und bei denen man von Außen nicht weiß, wie der Automat funktioniert.
Wenn ich jetzt korrekter mit Invarianten bzw. von Außen gesteuerten Übergängen arbeiten will, bekomme ich statt 3 Zuständen mit je einer eval() Funktion, für jede Zeile eine Übergangsfunktion in der die eigentliche Arbeit stattfindet.
Dafür wird es aber ziemlich eklig, die Übergänge zu formulieren. Deren Bedingungen können sich ja überschneiden. Klassischerweise gilt dann "wer zuerst kommt ...". Um da noch Ordnung reinzubekommen, muss ich dann wieder umständliches "wenn x UND y NICHT dann ..."
Hat jemand Ideen, wie sich sowas angenehm umsetzen lässt? Mir gehts weniger um eine theoretisch korrekte Variante, als um eine bei der man von Außen einigermaßen sehen kann, wie der Automat aufgebaut ist (bzw. die Struktur vorgeben kann) und die Funktionen im Inneren nicht zu komplex werden.
Deren Verhalten soll nun durch einen "Zustandsautomaten" abgebildet werden. Die "" deshalb, weil es kein der Theorie nach korrekter Automat sein muss, sondern letztlich darum geht, das Verhalten einigermaßen zu sortieren.
Im Prinzip stehe ich da jetzt vor der Variante eine Zustandsklasse zu verwenden, deren eval() Funktion die aktuelle Situation auf dem Zeichenbrett verarbeitet und einen Folgezustand zurückgibt. (kann auch wieder der aktuelle Zustand sein)
Das funktioniert auch, ist aber ziemlich "dreckig", weil man von Außen gar nicht mehr weiß, wie der Automat aufgebaut ist. Eigentlich ist das mehr eine Art Token-Passing.
Einfaches Beispiel:
Z0: Maus drücken -> Z1 + "nichts machen"
Z1: Maus mehr als X bewegen -> Z2 + "Linie beginnen"
Z1: Maus innerhalb von Y ms anheben -> Z0 + "Blinksignal am Cursor Zeichnen"
Z1: Maus nach Y ms anheben -> Z0 + "nichts machen"
Z2: Maus bewegen -> Z2 + "Linie fortsetzen"
Z2: Maus anheben -> Z0 + "Linie beenden"
Das sind in etwa die logischen Zustände aus einem noch ziemlich einfachen Beispiel.
Die primitive Variante macht daraus 3 Zustände, deren eval() Funktionen dann aber nicht komplett statisch sind (lässt sich mit externen Properties verbessern) und bei denen man von Außen nicht weiß, wie der Automat funktioniert.
Wenn ich jetzt korrekter mit Invarianten bzw. von Außen gesteuerten Übergängen arbeiten will, bekomme ich statt 3 Zuständen mit je einer eval() Funktion, für jede Zeile eine Übergangsfunktion in der die eigentliche Arbeit stattfindet.
Dafür wird es aber ziemlich eklig, die Übergänge zu formulieren. Deren Bedingungen können sich ja überschneiden. Klassischerweise gilt dann "wer zuerst kommt ...". Um da noch Ordnung reinzubekommen, muss ich dann wieder umständliches "wenn x UND y NICHT dann ..."
Hat jemand Ideen, wie sich sowas angenehm umsetzen lässt? Mir gehts weniger um eine theoretisch korrekte Variante, als um eine bei der man von Außen einigermaßen sehen kann, wie der Automat aufgebaut ist (bzw. die Struktur vorgeben kann) und die Funktionen im Inneren nicht zu komplex werden.