Arbeiten mit Zustandsdiagrammcode

www.altova.com Dieses Kapitel drucken Vorherige Seite Eine Ebene nach oben Nächste Seite

Startseite >  UML-Diagramme > Verhaltensdiagramme > Zustandsdiagramm >

Arbeiten mit Zustandsdiagrammcode

Die übergeordnete Klasse des Zustandsdiagramms (d.h. die "Controller-Klasse" oder "Kontextklasse") bildet die einzige Schnittstelle zwischen dem Benutzer des Zustandsdiagramms und der Zustandsdiagrammimplementierung.

 

Die Controller-Klasse bietet Methoden, mit Hilfe derer die Zustandsdiagramme von "außen" her geändert werden können (z.B. nachdem externe Ereignisse eingetreten sind).

 

Bei der Implementierung des Zustandsdiagramms werden dagegen Controller-Klassenmethoden ("Callbacks") aufgerufen, um den Benutzer des Zustandsdiagramms über Zustandsänderungen (OnEntry, OnExit, ...), Transitionseffekte und die Möglichkeit Methoden für Bedingungen (Guards) außer Kraft zu setzen und zu implementieren, zu informieren.

 

UModel kann einfache Operationen (ohne Parameter) für Entry/Exit/Do-Verhalten, Transitionseffekte, ...automatisch erstellen, wenn die entsprechende Option aktiviert ist. (siehe auch Erstellen von Zuständen, Aktivitäten und Transitionen). Diese Methoden können in UModel beliebig (durch Hinzufügen von Parametern, Definieren der Parameter als abstrakt, usw.) geändert werden.

 

Ein Zustandsdiagramm (d.h. seine Controller-Klasse) kann mehrmals instantiiert werden. Alle Instanzen sind unabhängig voneinander.

 

Die Ausführung des UML-Zustandsdiagramms ist für das Modell: Bis zur Fertigstellungen ausführen" konzipiert.
UML-Zustandsautomaten gehen davon aus, dass jedes Ereignis abgeschlossen ist, bevor das nächste verarbeitet wird.
Dies bedeutet auch, dass keine Entry/Exit/Do-Aktion oder kein Transitionseffekt eine neue Transition/eine Zustandsänderung direkt auslösen darf.

 

Initialisierung

Jede Region eines Zustandsdiagramms muss einen Anfangszustand haben.
Der von UModel generierte Code initialisiert alle Regionen des Zustandsdiagramms automatisch (oder bei Aufruf der Initialize()-Methode der Controller-Klasse).
Wenn OnEntry-Ereignisse bei der Initialisierung nicht erwünscht sind, können Sie die Initialize()-Methode manuell aufrufen und OnEntry-Ereignisse beim Start ignorieren.

 

Abrufen des/der aktuellen Zustands/Zustände

UModel unterstützt sowohl zusammengesetzte Zustände als auch orthogonale Zustände, d.h. es gibt nicht nur einen aktuellen Zustand, sondern jede Region (auf jeder hierarchischen Ebene) kann einen aktuellen Zustand haben.

 

Im Beispiel "AirCondition" wird gezeigt, wie die Regionen des aktuellen Zustands / der aktuellen Zustände durchlaufen werden.

 

TreeNode rootNode = m_CurrentStateTree.Nodes.Add(m_STM.getRootState().getName());

UpdateCurrentStateTree(m_STM.getRootState(), rootNode);

 

private void UpdateCurrentStateTree(AirCondition.AirConditionController.IState state, TreeNode node)

{

foreach (AirCondition.AirConditionController.IRegion r in state.getRegions())

{

TreeNode childNode = node.Nodes.Add(r.getName() + " : " + r.getCurrentState().getName());

UpdateCurrentStateTree(r.getCurrentState(), childNode);

}

}

 

Beispiel 1 - eine einfache Transition

 

SimpleTransition11

 

Die entsprechende Operation wird in UModel automatisch generiert.

 

SimpleTransition12

 

Generierte Methode im Code:

 

private class CTestStateMachine : IState
{
     
      public bool MyEvent1()
      {
             
      }
}

 

 

Der Benutzer des Zustandsdiagramms sollte die generierte Methode "MyEvent1" aufrufen, wenn das entsprechende Ereignis (außerhalb des Zustandsautomaten) eintritt.
Der Rückgabeparameter dieser Ereignismethoden liefert Informationen, ob das Ereignis eine Zustandsänderung verursacht hat (d.h. ob es eine Auswirkung auf das Zustandsdiagramm hat) oder nicht. Wenn sich der Automat z.B. im "State1" befindet und "MyEvent1()" eintritt, so ändert sich der aktuelle Status in "State2" und "MyEvent1()" gibt "true" zurück. Wenn "State2" aktiv ist und "MyEvent1()" eintritt, ändert sich nichts am Zustandsdiagramm und MyEvent1() gibt "false" zurück.

 

Beispiel 2 - eine einfache Transition mit einem Effekt

 

SimpleTransition21

 

Die entsprechende Operation wird in UModel automatisch generiert.

SimpleTransition22

Generierte Methode im Code:

 

private class CTestStateMachine : IState
{
     
      // Override to handle entry/exit/do actions, transition effects,...:
      public virtual void OnState1State2Effect() {}
}

 

"OnState1State2Effect()" wird immer dann von der Zustandsdiagrammimplementierung aufgerufen, wenn die Transition zwischen "State1" und "State2" ausgelöst wird.
Als Reaktion auf diesen Effekt sollte "OnState1State2Effect()" in einer abgeleiteten Klasse von "CTestStateMachine" außer Kraft gesetzt werden.
"CTestStateMachine:: OnState1State2Effect()" kann auch auf "abstract" gesetzt werden und Sie erhalten Kompilierfehler bis die Methode außer Kraft gesetzt wird.
Wenn "OnState1State2Effect()" nicht "abstract" ist und die Option "Debug-Meldungen generieren" aktiv ist, generiert UModel die folgende Debug-Ausgabe:

 

// Override to handle entry/exit/do actions, transition effects,...:
public virtual void OnState1State2Effect() {OnDebugMessage("ACTION: OnState1State2Effect");}

 

 

Beispiel 3 - eine einfache Transition mit einem Effekt-Parameter

 

SimpleTransition31

 

Die entsprechende Operation wird in UModel automatisch generiert.

SimpleTransition32

Generierte Methode im Code:

 

private class CTestStateMachine : IState
{
     
      // Additional defined operations of the controller class:
      public virtual void OnState1State2Effect(String text)
      {
      }
}

 

 

Zur Durchführung von (automatisch mit UModel erzeugten) Operationen können Parameter manuell hinzugefügt werden (UModel kann nicht wissen, welcher Typ benötigt wird).
In diesem Beispiel wurde der Parameter "text:String" zur Effekt-Methode in TestController hinzugefügt. Beim Aufruf dieser Methode muss ein ordnungsgemäßes Argument definiert werden (hier: "1 => 2").
Eine andere Möglichkeit wäre z.B. die folgende: Aufruf von statischen Methoden ("MyStatic.OnState1State2Effect("1 => 2")") oder Methoden von Singletons ("getSingleton().OnState1State2Effect("1 => 2")").

 

Beispiel 4 - entry/exit/do-Aktionen

SimpleTransition41

 

Die entsprechenden Operationen werden in UModel automatisch generiert.

SimpleTransition32

Generierte Methode im Code:

 

private class CTestStateMachine : IState
{
     
      // Override to handle entry/exit/do actions, transition effects,...:
      public virtual void OnExitState3() {}
      public virtual void OnEntryState4() {}
      public virtual void OnDoState4() {}
}

 

Zustände können entry/exit/do-Verhalten aufweisen. UModel generiert automatisch die entsprechenden Operationen zu deren Behandlung.
Wenn im Beispiel oben "MyEvent2()" eintritt, ruft die Zustandsdiagrammimplementierung "OnExitState3()" auf. Wenn "MyEvent2" einen Effekt hätte, würde dieser in der Folge aufgerufen werden. Anschließend würden "OnEntryState4" und "OnDoState4" aufgerufen werden.
Normalerweise sollten diese Methoden außer Kraft gesetzt werden. Wenn sie nicht abstrakt sind und die Option "Debug-Meldungen generieren" aktiv ist, liefert UModel eine Standard-Debug-Ausgabe, wie in Beispiel 2 beschrieben.
Diese Methoden können auch Parameter haben, wie in Beispiel 3 gezeigt.

 

Beispiel 5 - Guards

Transitionen können Guards (Wächterausdrücke) haben, die ermitteln, ob die Transition wirklich ausgelöst werden kann.

 

SimpleTransition51

 

Die entsprechende Operation wird in UModel automatisch generiert.

SimpleTransition52

Generierte Methode im Code:

 

private class CTestStateMachine : IState
{
     
      // Additional defined operations of the controller class:
      public virtual bool CanGoState6()
      {
          return true; // Override!
      }
}

 

Wenn "State5" der aktive Zustand ist und "MyEvent2" eintritt, so ruft die Zustandsdiagrammimplementierung "CanGoState6" auf und je nach Ergebnis wird die Transition ausgelöst oder nicht.
Normalerweise sollten diese Methoden außer Kraft gesetzt werden. Wenn sie nicht abstrakt sind und die Option "Debug-Meldungen generieren" aktiv ist, liefert UModel eine Standard-Debug-Ausgabe, wie in Beispiel 2 beschrieben.
Diese Methoden können auch Parameter haben, wie in Beispiel 3 gezeigt.
Es sind mehrere Transitionen mit demselben Ereignis aber unterschiedlichen Guards möglich. Die Reihenfolge, in der die verschiedenen Guards abgefragt werden, ist nicht definiert. Wenn eine Transition keinen Guard hat oder der Guard "else" ist, wird sie als der letzte Guard betrachtet (d.h. dieser Guard wird nur dann ausgelöst, wenn alle anderen Transitions-Guards "false" zurückgeben). So ist z.B. im Diagramm unten nicht definiert, ob CanGoState6() oder CanGoState7() zuerst aufgerufen wird. Die dritte Transition wird nur ausgelöst, wenn CanGoState6() und CanGoState7() false zurückgeben.

 

SimpleTransition6

 

Weitere Konstrukte und Funktionalitäten finden Sie in den Beispielen AirCondition.ump und Complex.ump.


© 2019 Altova GmbH