PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Zustandsübergänge/Transitionen in C++


komplett
2007-09-28, 14:29:44
Hallo, ich habe in einer Klasse aktuell ein (großes) enum-Feld, das den Status eines Objekts widerspiegelt. Das Problem ist, daß nur Übergänge von bestimmten Stati in andere gültige sind.

Ich habe momentan riesige if/else/switch Blöcke, welche häßlich zu überblicken und fehleranfällig sind, sowie schlecht erweiterbar. Ich überlege, wie man dies eleganter darstellen kann.

Hat jemand dazu Ideen wie man sowas löst? Wie man kompakt Übergänge von einem Status in einen anderen darstellen und beschreiben kann. Überprüfen kann in welchem Status man sich befindet bzw. in welchen Status man jetzt gehen muß? DANKE

del_4901
2007-09-28, 14:37:31
http://de.wikipedia.org/wiki/Zustand_%28Entwurfsmuster%29

Hier gleich bestellen:
http://www.amazon.de/Entwurfsmuster-Elemente-wiederverwendbarer-objektorientierter-Programmers/dp/3827321999

Ich bevorzuge aber das Original:
http://www.amazon.de/Patterns-Elements-Reusable-Object-Oriented-Software/dp/0201633612

Besserwissend
2007-09-28, 20:33:21
Richtig sexy ist meiner Meinung nach die Implementierung von Statecharts (StatePattern) nach Samek:
http://www.amazon.de/Practical-Statecharts-Programming-Embedded-Systems/dp/1578201101/ref=sr_1_1/303-9678895-7579450?ie=UTF8&s=books-intl-de&qid=1191001491&sr=1-1

Vielleicht reicht auch schon der Auszug aus dem Buch:
http://www.quantum-leaps.com/writings/PSiCC_Excerpts.pdf

Entgegen dem Titel sind die Implementierungsmöglichkeiten nicht auf eingebettete Systeme beschränkt

Es gibt übrigens einen Haufen Entwurfsmuster für Objekte und deren Zustände (StatePattern):
http://www.hillside.net/plop/plop2003/Papers/Adamczyk-State-Machine.pdf

Hier mal ein ganz einfacher Ansatz, ohne den "nested-switch" oder kaskadierte-ifs:
Wenn es um eine _kompakte_ Darstellung geht, ist eine Tabelle (2dimensionales Array) das Beste, geht aber auf Kosten des Speichers (dünnbesetzt)

für einen Zustandswechsel geht das so:

meinObjekt.setState( ereignis );


Methode setState in Pseudocode würde so aussehen

...
private int state;
public setState ( int e ) {
state:=matrix[state][e];
}
...


Man kann statt simplen Array auch eine Hashtable nehmen oder die Matrix mit Row Displacement Dispatching komprimieren (NP-vollständig! => wenige Zustände <20 oder Heuristik wie randomisierte bzw. Approximationsalgorithmen ), das ist dann kompakt, schnell und speichersparender.

me²
2007-09-29, 11:25:04
Hallo, ich habe in einer Klasse aktuell ein (großes) enum-Feld, das den Status eines Objekts widerspiegelt. Das Problem ist, daß nur Übergänge von bestimmten Stati in andere gültige sind.

Spontan fällt mir da Adjacency Matrix (http://en.wikipedia.org/wiki/Modified_adjacency_matrix) ein.

O(1) bei der Frage, ob ein Übergang von A in B gestattet ist, O(n) bei der Frage, welche Übergänge von A gestattet sind.

Das ganze ist dann auch einfach zu pflegen und erweiterbar.

PS: Einfache Lösung sind meistens die besten :)

del_4901
2007-09-29, 11:28:41
Spontan fällt mir da Adjacency Matrix (http://en.wikipedia.org/wiki/Modified_adjacency_matrix) ein.

O(1) bei der Frage, ob ein Übergang von A in B gestattet ist, O(n) bei der Frage, welche Übergänge von A gestattet sind.

Das ganze ist dann auch einfach zu pflegen und erweiterbar.

PS: Einfache Lösung sind meistens die besten :)
Das ändert aber nichts am if/else/switch Konstrukt. Das ist das gleiche Problem nur anders verpackt.

me²
2007-09-29, 11:52:24
Das ändert aber nichts am if/else/switch Konstrukt. Das ist das gleiche Problem nur anders verpackt.
nein,

Das Zustandsübergangsschema kann ja als gerichteter Graph dargestellt werden. Sämtliche Kanten des Graphen werden in einer Matrix gespeichert. Für die Frage, ob ein Übergang erlaubt ist, braucht es dann nur einen kurzen Blick in den Graph bzw. der Zeile/Spalte der Matrix.

Die if/then/else - switch Konstruktur entfallen: Diese Information ist in der Matrix gespeichert.

del_4901
2007-09-29, 12:45:28
nein,

Das Zustandsübergangsschema kann ja als gerichteter Graph dargestellt werden. Sämtliche Kanten des Graphen werden in einer Matrix gespeichert. Für die Frage, ob ein Übergang erlaubt ist, braucht es dann nur einen kurzen Blick in den Graph bzw. der Zeile/Spalte der Matrix.

Die if/then/else - switch Konstruktur entfallen: Diese Information ist in der Matrix gespeichert.
Irgendwann muss entschieden werden, was in dem Zustand gemacht werden soll.
Was man mit dem Graphen nur geschafft hat, ist das man diesen (eher kleinen teil) des Übergangs auslagern konnte. Das bringt also keine Vorteile.

Trap
2007-09-29, 14:01:25
Irgendwann muss entschieden werden, was in dem Zustand gemacht werden soll.
Der Fragesteller hat nicht gesagt, dass irgendwas gemacht werden soll. Die Anforderung hast du einfach erfunden, damit deine Antwort sinnvoll ist :biggrin:

del_4901
2007-09-29, 14:56:13
Der Fragesteller hat nicht gesagt, dass irgendwas gemacht werden soll. Die Anforderung hast du einfach erfunden, damit deine Antwort sinnvoll ist :biggrin::rolleyes: omg, das ist doch einfach logisch weitergedacht.

<- SW-Architekten haben immer dieses Problem, dafür haben wir meißtens (irgendwann) recht.