Máquina de estado de ardilla: desde la exploración de principios hasta las mejores prácticas

Autor: JD Logística Zheng Penghui

1. Introducción

La máquina de estado Squirrel es una herramienta para el modelado del comportamiento de objetos, que describe principalmente el estado que experimenta el objeto en su ciclo de vida y cómo responder a diversos eventos del mundo exterior. Por ejemplo, el estado de creación de pedidos, pago, entrega, cosecha, cancelación, etc., el control entre estados y el monitoreo de eventos desencadenantes se pueden administrar y realizar claramente mediante este marco. Los beneficios de usar una máquina de estado para administrar el flujo de vida de los objetos se reflejan más en la mantenibilidad y la capacidad de prueba del código. Las condiciones de estado claras, las acciones de respuesta atómica y los estados objetivo de migración impulsados ​​​​por eventos se pueden usar para escenarios comerciales con complejos y procesos cambiables Reduce en gran medida la dificultad de mantenimiento y prueba.

2 Conceptos básicos

2.1 Definición de máquina de estado de ardilla

La máquina de estados de ardilla es una máquina de estados finitos. Una máquina de estados finitos significa que un objeto tiene un flujo de vida claro y complejo (generalmente más de tres estados), y existen diferentes condiciones de activación y comportamientos de procesamiento en las transiciones de estado.

2.2 Elementos de la máquina de estado de ardilla

La máquina de estado Squirrel se puede resumir en cuatro elementos, a saber, estado actual, condición, acción y estado siguiente. El "estado actual" y la "condición" son la causa, y la "acción" y el "estado siguiente" son el efecto.

  • Estado actual: se refiere al estado actual.
  • Condiciones: También conocidas como eventos. Cuando se cumple una condición, se activará una acción o se realizará una transición de estado.
  • Acción: La acción que se ejecutará después de que se cumpla la condición. Una vez que se ejecuta la acción, puede migrar a un nuevo estado o puede permanecer en el estado original. No se requieren acciones. Cuando se cumplen las condiciones, puede migrar directamente al nuevo estado sin realizar ninguna acción.
  • Estado siguiente: el nuevo estado al que se va a pasar después de que se cumpla la condición. El "estado secundario" es relativo al "estado actual". Una vez que se activa el "estado secundario", se transformará en un nuevo "estado actual".

3 Principio de implementación

3.1 CASO de auditoría de tienda

Por ejemplo, la apertura de una tienda en línea JD.com debe revisarse antes de que pueda lanzarse oficialmente. El estado de la tienda es pendiente de revisión, rechazado y revisado. Las operaciones correspondientes incluyen envío para revisión, aprobación y rechazo de revisión. Ahora es necesario darse cuenta de los requisitos de un proceso de revisión de la tienda.

3.2 Comparación de esquemas

3.2.1 Implementación if-else o switch-case de uso común (modo de bifurcación)

Figura 1. Diagrama de flujo de la implementación del modo if-else/switch-case

3.2.2 Implementación de la máquina de estados


 

Figura 2. Diagrama de flujo de implementación del modo de máquina de estado

3.2.3 Comparación

Al introducir una máquina de estado, se puede eliminar una gran cantidad de estructuras de rama if-else if-else o switch-case, y la tabla basada en el comportamiento se puede consultar directamente a través del estado actual y la tabla basada en el estado para encontrar comportamientos específicos. y realizar operaciones, lo que favorece el mantenimiento y la expansión del código.

3.3 Principio de implementación

 

Figura 3. Diagrama de flujo de creación de máquinas de estado

 

  • StateMachine: la instancia de StateMachine es creada por StateMachineBuilder y no se comparte. Para StateMachine definida por anotación (o api fluida), la instancia de StateMachine se crea de acuerdo con esta definición, y la acción correspondiente también es ejecutada por esta instancia. La integración final con spring es hablar de spring La instancia del bean se inyecta en la instancia de la máquina de estado creada por el constructor;
  • StateMachineBuilder: Esencialmente un proxy dinámico creado por StateMachineBuilderFactory. La implementación predeterminada del StateMachineBuilder con proxy es StateMachineBuilderImpl, que describe internamente los detalles de la creación de la instancia de la máquina de estado, incluido el estado, el evento, la información del tipo de contexto, el constructor, etc., y también incluye algunos recursos compartidos globales de StateMachine, incluidos StateConverter, EventConverter, MvelScriptManager, etc. StateMachineBuilder se puede reutilizar y se puede implementar como un singleton en uso;
  • StateMachineBuilderFactory: una instancia de proxy dinámica creada para StateMachineBuilder;

4 Practica compartir

4.1 Dependencia del entorno

<dependency>
<groupId>org.squirrelframework</groupId>
<artifactId>squirrel-foundation</artifactId>
<version>0.3.9</version>
</dependency>

4.2 Definición de elementos de máquina de estado: estado, evento

// 店铺审核状态
public Enum ShopInfoAuditStatusEnum{
audit(0,"待审核"),
agree(1,"审核通过"),
reject(2,"审核驳回");
}
// 店铺审核事件
public Enum ShopInfoAuditEvent{
SUBMIT, // 提交
AGREE, // 同意
REJECT; // 驳回
}

 

4.3 Construya una instancia de StateMachineBuilder

/**
* StateMachineBuilder实例
*/
public class StateMachineEngine <T extends UntypedStateMachine, S, E, C> implements ApplicationContextAware{


private ApplicationContext applicationContext;


private static Map<String,UntypedStateMachineBuilder> builderMap = new HashMap<String,UntypedStateMachineBuilder>();

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}


@Transactional
public void fire(Class<T> machine, S state, E event, C context) {
StateMachineBuilder stateMachineBuilder = this.getStateMachineBuilder(machine);
StateMachine stateMachine = stateMachineBuilder.newStateMachine(state,applicationContext);
stateMachine.fire(event, context);
}


private StateMachineBuilder getStateMachineBuilder(Class<T> stateMachine){
UntypedStateMachineBuilder stateMachineBuilder = builderMap.get(stateMachine.getName());
if(stateMachineBuilder == null){
stateMachineBuilder = StateMachineBuilderFactory.create(stateMachine,ApplicationContext.class);
builderMap.put(stateMachine.getName(),stateMachineBuilder);
}
return stateMachineBuilder;

4.4 Crear una máquina de estado de revisión de estado de tienda específica

/**
* 店铺审核状态机
*/
@States({
@State(name = "audit"),
@State(name = "agree"),
@State(name = "reject")
})
@Transitions({
@Transit(from = "audit", to = "agree", on = "AGREE", callMethod = "agree"),
@Transit(from = "audit", to = "reject", on = "REJECT", callMethod = "reject"),
@Transit(from = "reject", to = "audit", on = "SUBMIT", callMethod = "submit"),
@Transit(from = "agree", to = "audit", on = "SUBMIT", callMethod = "submit"),
@Transit(from = "audit", to = "audit", on = "SUBMIT", callMethod = "submit"),
})
@StateMachineParameters(stateType=ShopInfoAuditStatusEnum.class, eventType=ShopInfoAuditEvent.class, contextType=ShopInfoAuditStatusUpdateParam.class)
public class ShopInfoAuditStateMachine extends AbstractUntypedStateMachine {


private ApplicationContext applicationContext;


public ShopInfoAuditStateMachine(){}


public ShopInfoAuditStateMachine(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}


// 审核通过业务逻辑
public void agree(ShopInfoAuditStatusEnum fromState, ShopInfoAuditStatusEnum toState, ShopInfoAuditEvent event, ShopInfoAuditStatusUpdateParam param) {
this.agree(fromState,toState,event,param);
}

// 审核驳回业务逻辑
public void reject(ShopInfoAuditStatusEnum fromState, ShopInfoAuditStatusEnum toState, ShopInfoAuditEvent event, ShopInfoAuditStatusUpdateParam param) {
this.reject(fromState,toState,event,param);
}

// 提交业务逻辑
public void submit(ShopInfoAuditStatusEnum fromState, ShopInfoAuditStatusEnum toState, ShopInfoAuditEvent event, ShopInfoAuditStatusUpdateParam param) {
this.submit(fromState,toState,event,param);
}

 

4.5 Llamadas de clientes

// 调用端
main{
StateMachineEngine stateMachineEngine = applicationContext.getBean(StateMachineEngine.class);
// 审核通过调case
stateMachineEngine.fire(ShopInfoAuditStateMachine.class,ShopInfoAuditStatusEnum.audit,ShopInfoAuditEvent.AGREE,param);
// 审核驳回case
stateMachineEngine.fire(ShopInfoAuditStateMachine.class,ShopInfoAuditStatusEnum.audit,ShopInfoAuditEvent.REJECT,param);
}

 

5 resumen

La máquina de estado nos ayuda a lidiar con el flujo de estados de objetos, el monitoreo de eventos y la respuesta a varios eventos externos. Desde la perspectiva del diseño del código, se reduce una gran cantidad de juicios lógicos if-else/switch-case, lo que mejora la capacidad de mantenimiento y la escalabilidad del código, y facilita la gestión y las pruebas.

{{o.nombre}}
{{m.nombre}}

Supongo que te gusta

Origin my.oschina.net/u/4090830/blog/6822669
Recomendado
Clasificación