Altova UModel 2024

La clase primaria de la máquina de estados (es decir, la clase controladora controller o la clase de contexto) es la única interfaz que existe entre el usuario de la máquina de estados y su implementación.

 

La clase controladora controller aporta los métodos que se pueden usar desde "fuera" para cambiar los estados (p. ej. después de que tengan lugar eventos externos).

 

No obstante, la implementación de la máquina de estados llama a los métodos de la clase controller (devoluciones de llamada) para informar al usuario de la máquina de estados sobre cambios de estado (OnEntry, OnExit, ...), efectos de las transiciones y la posibilidad de invalidar e implementar métodos para condiciones (guardas).

 

UModel puede crear operaciones simples (sin parámetros) automáticamente para comportamientos entrar/salir/hacer, efectos de transición, etc. cuando se activa la opción correspondiente (consulte el apartado Crear estados, actividades y transiciones.) Estos métodos se pueden cambiar (añadiéndoles parámetros, configurándolos como métodos abstractos, etc.).

 

Puede generar instancias de una máquina de estados (es decir, de su clase controladora controller) y todas las instancias funcionan independientemente.

 

La ejecución de la máquina de estados UML está diseñada para el modelo de ejecución hasta el final.

Las máquinas de estados UML suponen que el procesamiento de cada evento finaliza antes de que empiece a procesarse el siguiente evento.

Esto también significa que las acciones entrar/salir/hacer y los efectos de las transiciones no pueden disparar transiciones/cambios de estado nuevos directamente.

 

Inicialización

Cada región de una máquina de estados debe tener un estado inicial.

El código generado con UModel inicializa automáticamente todas las regiones de la máquina de estados (o cuando se llama al método Initialize() de la clase controladora).

Si no necesita eventos OnEntry durante la inicialización, puede llamar a mano al método Initialize() e ignorar los eventos OnEntry durante el inicio.

 

Obtener el estado actual

UModel admite estados compuestos y estados ortogonales, así que no hay un solo estado actual: cada región (de cualquier nivel jerárquico) puede tener un estado actual.

 

En el proyecto de ejemplo AirCondition.ump puede ver cómo se pueden recorrer las regiones hasta llegar a los estados actuales:

 

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);
  }
}

 

Ejemplo nº1: una transición simple

SimpleTransition11

La operación correspondiente se genera automáticamente en UModel.

 

SimpleTransition12

Método generado en el código:

 

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

 

Notas:

 

El usuario de la máquina de estados debería llamar al método generado "MyEvent1" cuando tenga lugar el evento correspondiente (fuera de la máquina de estados).

El parámetro de devolución de estos métodos-evento aporta información si el evento provocó un cambio de estado (es decir, si tuvo un efecto o no en la máquina de estados). Por ejemplo, si "State1" está activo y ocurre el evento "MyEvent1()", entonces el estado actual cambia a "State2" y "MyEvent1()" devuelve true. Si "State2" está activo y ocurre el evento "MyEvent1()", nada cambia en la máquina de estados y MyEvent1() devuelve false.

 

Ejemplo nº2: una transición simple con un efecto

SimpleTransition21

 

La operación correspondiente se genera automáticamente en UModel

SimpleTransition22

Método generado en el código:

 

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

 

Notas:

 

La implementación de la máquina de estados llamará a "OnState1State2Effect()" cuando se dispare la transición del estado "State1" al estado "State2".

Para reaccionar a este efecto "OnState1State2Effect()" debería sobrescribirse en una clase derivada de "CTestStateMachine".

"CTestStateMachine:: OnState1State2Effect()" también puede configurarse como abstract y obtendrá errores de compilación hasta que se sobrescriba el método.

Cuando "OnState1State2Effect()" no es abstracto y está activa la opción Generar mensajes de depuración, UModel genera este resultado:

 

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

 

Ejemplo nº3: una transición simple con un efecto y un parámetro

SimpleTransition31

La operación correspondiente se genera automáticamente en UModel.

SimpleTransition32

Método generado en el código:

 

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

 

Notas:

 

Para llevar a cabo las operaciones (creadas automáticamente por UModel), puede añadir parámetros manualmente (UModel no puede conocer el tipo necesario).

En este ejemplo el parámetro "text:String" se añadió al método Effect de TestController. Es necesario especificar un argumento adecuado cuando se llame a este método (en este caso: "1 => 2").

Otra posibilidad es llamar a los métodos estáticos ("MyStatic.OnState1State2Effect("1 => 2")") o a los métodos de singleton ("getSingleton().OnState1State2Effect("1 => 2")").

 

Ejemplo nº4: acciones entrar/salir/hacer

SimpleTransition41

Las operaciones correspondientes se generan automáticamente en UModel.

SimpleTransition32

 

Método generado en el código:

 

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() {}
}

 

Notas:

 

Los estados pueden tener comportamientos entrar/salir/hacer. UModel crea automáticamente las operaciones necesarias para ellos.

Cuando tiene lugar "MyEvent2()", la implementación de la máquina de estados llama a "OnExitState3()", si "MyEvent2" tuviera un efecto, se le llamaría después y posteriormente se llamaría a "OnEntryState4" y "OnDoState4".

Por lo general estos métodos deberían sobrescribirse. Cuando no son abstractos y está activa la opción Generar mensajes de depuración, UModel genera el resultado que se describe en el ejemplo nº2.

Estos métodos también pueden tener los parámetros que aparecen en el ejemplo nº3.

 

Ejemplo nº5: guardas

Las transiciones pueden tener guardas, que determinan si la transición se dispara realmente.

 

SimpleTransition51

La operación correspondiente se genera automáticamente en UModel.

SimpleTransition52

Método generado en el código:

 

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

 

Notas:

 

Si "State5" es el estado activo y tiene lugar "MyEvent2", la implementación de la máquina de estados llamará a "CanGoState6" y, dependiendo de su resultado, la transición se disparará o no.

Por lo general estos métodos deberían sobrescribirse. Cuando no son abstractos y está activa la opción Generar mensajes de depuración, UModel genera el resultado que se describe en el ejemplo nº2.

Estos métodos también pueden tener los parámetros que aparecen en el ejemplo nº3.

Varias transiciones pueden tener el mismo evento, pero guardas diferentes. No hay un orden definido para sondear los guardas. Si una transición no tiene guarda o si su guarda es "else", se trata como la última transición (es decir, esta transición solo se disparará si los guardas de las demás transiciones devuelven false. Por ejemplo, no está definido si primero se dispara CanGoState6 o CanGoState7, pero lo que está claro es que la tercera transición solo se disparará si CanGoState6 y CanGoState7 devuelven false.

SimpleTransition6

Para ver más funciones y construcciones consulte los ejemplos de los archivos AirCondition.ump y Complex.ump.

 

© 2017-2023 Altova GmbH