引言:狀態(tài)管理的困境與解決方案
你是否還在為業(yè)務(wù)系統(tǒng)中的狀態(tài)流轉(zhuǎn)邏輯混亂而頭疼?訂單從創(chuàng)建到支付再到發(fā)貨的狀態(tài)變化,用戶(hù)從注冊(cè)到認(rèn)證再到活躍的生命周期管理,這些復(fù)雜的狀態(tài)流轉(zhuǎn)往往導(dǎo)致代碼中充斥著大量的if-else判斷和狀態(tài)檢查,不僅難以維護(hù),還容易引發(fā)bug。
一、狀態(tài)機(jī)核心概念與COLA組件架構(gòu)
狀態(tài)機(jī)基礎(chǔ)概念
狀態(tài)機(jī)(State Machine)是一種數(shù)學(xué)模型,用于描述對(duì)象在其生命周期中的狀態(tài)變化過(guò)程。在軟件工程中,狀態(tài)機(jī)模式常用于處理具有復(fù)雜狀態(tài)轉(zhuǎn)換的業(yè)務(wù)邏輯。核心概念包括:
- 狀態(tài)(State):對(duì)象在特定時(shí)間點(diǎn)的狀況,如訂單的"待支付"、"已支付"狀態(tài)
- 事件(Event):觸發(fā)狀態(tài)轉(zhuǎn)換的動(dòng)作或條件,如"支付成功"事件
- 轉(zhuǎn)換(Transition):從一個(gè)狀態(tài)到另一個(gè)狀態(tài)的變化過(guò)程
- 動(dòng)作(Action):在狀態(tài)轉(zhuǎn)換過(guò)程中執(zhí)行的業(yè)務(wù)邏輯
- 條件(Condition):判斷是否允許執(zhí)行某個(gè)狀態(tài)轉(zhuǎn)換的規(guī)則
二、cola-statemachine介紹
COLA框架的狀態(tài)機(jī)組件是一種輕量級(jí)的、無(wú)狀態(tài)的、基于注解的狀態(tài)機(jī)實(shí)現(xiàn),可以方便地管理訂單等業(yè)務(wù)對(duì)象的狀態(tài)轉(zhuǎn)換。COLA框架的狀態(tài)機(jī)使用了連貫接口(Fluent Interfaces)來(lái)定義狀態(tài)和事件,以及對(duì)應(yīng)的動(dòng)作和檢查。COLA框架的狀態(tài)機(jī)是COLA 4.0應(yīng)用架構(gòu)的一部分,旨在控制復(fù)雜度,提高開(kāi)發(fā)效率。
COLA框架的狀態(tài)機(jī)的優(yōu)勢(shì)有以下幾點(diǎn):
- 簡(jiǎn)化了狀態(tài)轉(zhuǎn)換的邏輯,避免了大量的if-else判斷
- 提高了代碼的可讀性和可維護(hù)性,方便了單元測(cè)試和重構(gòu)
- 支持多種狀態(tài)機(jī)模式,如同步、異步、延遲等
- 與COLA框架的其他組件協(xié)同工作,實(shí)現(xiàn)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)和六邊形架構(gòu)
2.2 COLA狀態(tài)機(jī)基礎(chǔ)模型
在Cola-StateMachine組件中有如下的抽象概念模型:
- 1.State:狀態(tài)
- 2.Event:事件,狀態(tài)由事件觸發(fā),引起變化
- 3.Transition:流轉(zhuǎn),表示從一個(gè)狀態(tài)到另一個(gè)狀態(tài)
- 4.External Transition:外部流轉(zhuǎn),兩個(gè)不同狀態(tài)之間的流轉(zhuǎn)
- 5.Internal Transition:內(nèi)部流轉(zhuǎn),同一個(gè)狀態(tài)之間的流轉(zhuǎn)
- 6.Condition:條件,表示是否允許到達(dá)某個(gè)狀態(tài)
- 7.Action:動(dòng)作,到達(dá)某個(gè)狀態(tài)之后,可以做什么
- 8.StateMachine:狀態(tài)機(jī)
2.3 COLA狀態(tài)機(jī)組件架構(gòu)
COLA框架的狀態(tài)機(jī)組件(cola-component-statemachine)采用面向?qū)ο笤O(shè)計(jì),提供了靈活的狀態(tài)流轉(zhuǎn)建模能力。其核心接口關(guān)系如下:

主要接口功能說(shuō)明:
- StateMachine:狀態(tài)機(jī)核心接口,提供事件觸發(fā)、狀態(tài)驗(yàn)證等方法
- State:狀態(tài)接口,管理從該狀態(tài)出發(fā)的所有轉(zhuǎn)換
- Transition:轉(zhuǎn)換接口,定義狀態(tài)間的轉(zhuǎn)換規(guī)則和行為
- StateMachineFactory:狀態(tài)機(jī)工廠(chǎng)類(lèi),負(fù)責(zé)狀態(tài)機(jī)的注冊(cè)和獲取
2.4 Cola-StateMachine鏈路圖

三、快速入門(mén):構(gòu)建你的第一個(gè)狀態(tài)機(jī)
3.1 基本狀態(tài)機(jī)實(shí)現(xiàn)步驟
使用COLA狀態(tài)機(jī)構(gòu)建業(yè)務(wù)流轉(zhuǎn)系統(tǒng)通常遵循以下步驟:
- 定義狀態(tài)和事件枚舉:確定業(yè)務(wù)領(lǐng)域中的狀態(tài)集合和觸發(fā)事件
- 創(chuàng)建上下文對(duì)象:封裝狀態(tài)轉(zhuǎn)換過(guò)程中需要傳遞的數(shù)據(jù)
- 構(gòu)建狀態(tài)機(jī):使用構(gòu)建器定義狀態(tài)間的轉(zhuǎn)換規(guī)則
- 注冊(cè)并獲取狀態(tài)機(jī)實(shí)例:通過(guò)工廠(chǎng)類(lèi)管理狀態(tài)機(jī)
- 觸發(fā)事件并處理結(jié)果:在業(yè)務(wù)邏輯中調(diào)用狀態(tài)機(jī)處理狀態(tài)轉(zhuǎn)換
3.2 環(huán)境準(zhǔn)備與依賴(lài)引入
要使用COLA狀態(tài)機(jī)組件,首先需要在項(xiàng)目中引入依賴(lài):
<dependency>
<groupId>com.alibaba.cola</groupId>
<artifactId>cola-component-statemachine</artifactId>
<version>最新版本</version>
</dependency>
3.3 定義訂單的實(shí)體類(lèi)、訂單狀態(tài)的枚舉值、訂單事件的枚舉值
@Getter
@AllArgsConstructor
public enum OrderState {
CREATED(0,"已創(chuàng)建"),
PAID(1,"已支付"),
SHIPPED(2,"已發(fā)貨"),
DELIVERED(3,"已送達(dá)"),
CANCELLED(4,"已取消"),
;
private final Integer code;
private final String msg;
}
@Getter
@AllArgsConstructor
public enum OrderEvent {
PAY(0,"支付"),
SHIP(1,"發(fā)貨"),
DELIVER(2,"送達(dá)"),
CANCEL(3,"取消"),
;
private final Integer code;
private final String msg;
}
@Data
@Builder
public class OrderContext {
@ApiModelProperty("訂單ID")
private Integer orderId;
@ApiModelProperty("用戶(hù)ID")
private String userId;
@ApiModelProperty("訂單金額")
private BigDecimal amount;
@ApiModelProperty("備注信息")
private String remark;
}
3.4 ColaStateMachineConfig,主要負(fù)責(zé) Cola StateMachine 的配置
public class ColaStateMachineConfig {
public StateMachineBuilder<OrderState, OrderEvent, OrderContext> createBuilder() {
// 3.1 創(chuàng)建狀態(tài)機(jī)構(gòu)建器
StateMachineBuilder<OrderState, OrderEvent, OrderContext> builder =
StateMachineBuilderFactory.create();
// 3.2 定義狀態(tài)轉(zhuǎn)換規(guī)則
// 已創(chuàng)建 -> 已支付 (支付事件)
builder.externalTransition()
.from(OrderState.CREATED)
.to(OrderState.PAID)
.on(OrderEvent.PAY)
.when(checkPaymentCondition())
.perform(updateOrderStatusAction());
// 已支付 -> 已發(fā)貨 (發(fā)貨事件)
builder.externalTransition()
.from(OrderState.PAID)
.to(OrderState.SHIPPED)
.on(OrderEvent.SHIP)
.when(checkStockCondition())
.perform(createShipmentAction());
// 已發(fā)貨 -> 已送達(dá) (送達(dá)事件)
builder.externalTransition()
.from(OrderState.SHIPPED)
.to(OrderState.DELIVERED)
.on(OrderEvent.DELIVER)
.perform(completeOrderAction());
// 已創(chuàng)建 -> 已取消 (取消事件)
builder.externalTransition()
.from(OrderState.CREATED)
.to(OrderState.CANCELLED)
.on(OrderEvent.CANCEL)
.when(checkCancelCondition())
.perform(cancelOrderAction());
return builder;
}
// 條件判斷:檢查支付條件
private static Condition<OrderContext> checkPaymentCondition() {
return context -> {
// 實(shí)際業(yè)務(wù)中可能檢查余額、支付方式等
System.out.println("檢查訂單[" + context.getOrderId() + "]的支付條件");
return context.getAmount().compareTo(BigDecimal.ZERO) > 0;
};
}
// 條件判斷:檢查庫(kù)存條件
private static Condition<OrderContext> checkStockCondition() {
return context -> {
// 實(shí)際業(yè)務(wù)中可能檢查商品庫(kù)存
System.out.println("檢查訂單[" + context.getOrderId() + "]的庫(kù)存狀況");
return true;
};
}
// 條件判斷:檢查取消條件
private static Condition<OrderContext> checkCancelCondition() {
return context -> {
// 實(shí)際業(yè)務(wù)中可能檢查取消時(shí)限、權(quán)限等
System.out.println("檢查訂單[" + context.getOrderId() + "]的取消條件");
return true;
};
}
// 動(dòng)作:更新訂單狀態(tài)
private static Action<OrderState, OrderEvent, OrderContext> updateOrderStatusAction() {
return (from, to, event, context) -> {
System.out.println("執(zhí)行訂單[" + context.getOrderId() + "]狀態(tài)更新: " + from + " -> " + to);
// 實(shí)際業(yè)務(wù)中可能更新數(shù)據(jù)庫(kù)記錄、發(fā)送通知等
};
}
// 動(dòng)作:創(chuàng)建物流單
private static Action<OrderState, OrderEvent, OrderContext> createShipmentAction() {
return (from, to, event, context) -> {
System.out.println("為訂單[" + context.getOrderId() + "]創(chuàng)建物流單");
// 實(shí)際業(yè)務(wù)中可能調(diào)用物流系統(tǒng)API
};
}
// 動(dòng)作:完成訂單
private static Action<OrderState, OrderEvent, OrderContext> completeOrderAction() {
return (from, to, event, context) -> {
System.out.println("訂單[" + context.getOrderId() + "]已完成,執(zhí)行后續(xù)處理");
// 實(shí)際業(yè)務(wù)中可能觸發(fā)積分發(fā)放、評(píng)價(jià)提醒等
};
}
// 動(dòng)作:取消訂單
private static Action<OrderState, OrderEvent, OrderContext> cancelOrderAction() {
return (from, to, event, context) -> {
System.out.println("訂單[" + context.getOrderId() + "]已取消,執(zhí)行取消處理");
// 實(shí)際業(yè)務(wù)中可能觸發(fā)退款、庫(kù)存釋放等
};
}
}
3.5 ColaStateMachineService,主要是封裝了狀態(tài)機(jī)的調(diào)用入口
@Service
@Slf4j
public class ColaStateMachineService {
private static final String MACHINE_ID = "orderStateMachine";
private StateMachine<OrderState, OrderEvent, OrderContext> stateMachine;
@PostConstruct
public void init() {
ColaStateMachineConfig config = new ColaStateMachineConfig();
StateMachineBuilder<OrderState, OrderEvent, OrderContext> stateMachineBuilder = config.createBuilder();
// 3.3 構(gòu)建并注冊(cè)狀態(tài)機(jī)
stateMachine = stateMachineBuilder.build(MACHINE_ID);
//StateMachineFactory.register(stateMachine);
}
public String getMachineId(){
return stateMachine.getMachineId();
}
public String generatePlantUML(){
return stateMachine.generatePlantUML();
}
public OrderState fireEvent(OrderState source, OrderEvent event, OrderContext context) {
return stateMachine.fireEvent(source, event, context);
}
public Boolean verify(OrderState source, OrderEvent event) {
return stateMachine.verify(source, event);
}
}
3.6 定義一個(gè) controller 的操作接口
@RequestMapping("/order")
@RestController
@Slf4j
public class OrderOperaController {
@Resource
private ColaStateMachineService colaStateMachineService;
/**
* 場(chǎng)景1-用戶(hù)支付訂單
*
* @return {@link Boolean}
*/
@PostMapping("/pay")
public Boolean pay() {
String machineId = colaStateMachineService.getMachineId();
System.out.println(machineId);
OrderContext order = OrderContext.builder().orderId(1).userId("USER_123").amount(new BigDecimal("99.99")).build();
OrderState orderState = colaStateMachineService.fireEvent(OrderState.CREATED, OrderEvent.PAY, order);
System.out.println(orderState.toString());
return true;
}
/**
* 場(chǎng)景2-訂單發(fā)貨
*
* @return {@link Boolean}
*/
@PostMapping("/ship")
public Boolean ship() {
String machineId = colaStateMachineService.getMachineId();
System.out.println(machineId);
OrderContext order = OrderContext.builder().orderId(1).userId("USER_123").amount(new BigDecimal("99.99")).build();
OrderState orderState = colaStateMachineService.fireEvent(OrderState.PAID, OrderEvent.SHIP, order);
System.out.println(orderState.toString());
return true;
}
/**
* 場(chǎng)景3-訂單送達(dá)
*
* @return {@link Boolean}
*/
@PostMapping("/deliver")
public Boolean deliver() {
String machineId = colaStateMachineService.getMachineId();
System.out.println(machineId);
OrderContext order = OrderContext.builder().orderId(1).userId("USER_123").amount(new BigDecimal("99.99")).build();
boolean canShip = colaStateMachineService.verify(OrderState.SHIPPED, OrderEvent.DELIVER);
System.out.println(canShip);
OrderState orderState = colaStateMachineService.fireEvent(OrderState.SHIPPED, OrderEvent.DELIVER, order);
System.out.println(orderState.toString());
return true;
}
/**
* 場(chǎng)景4-檢查錯(cuò)誤關(guān)閉訂單
*
* @return {@link Boolean}
*/
@PostMapping("/cancel")
public Boolean cancel() {
String machineId = colaStateMachineService.getMachineId();
System.out.println(machineId);
OrderContext order = OrderContext.builder().orderId(1).userId("USER_123").amount(new BigDecimal("99.99")).build();
OrderState orderState = colaStateMachineService.fireEvent(OrderState.CREATED, OrderEvent.CANCEL, order);
System.out.println(orderState.toString());
return true;
}
}
上述代碼定義了一個(gè)簡(jiǎn)單的訂單狀態(tài)機(jī),包含從創(chuàng)建到支付、發(fā)貨、送達(dá)的正常流程,以及從創(chuàng)建到取消的異常流程。每個(gè)狀態(tài)轉(zhuǎn)換都定義了觸發(fā)事件、前置條件和執(zhí)行動(dòng)作,使業(yè)務(wù)邏輯更加清晰和可維護(hù)。
四、COLA狀態(tài)機(jī)核心接口詳解
4.1 StateMachine接口
StateMachine接口是COLA狀態(tài)機(jī)組件的核心,定義了狀態(tài)機(jī)的基本操作:
public interface StateMachine<S, E, C> extends Visitable {
/**
* 驗(yàn)證事件是否可以從當(dāng)前狀態(tài)觸發(fā)
* @param sourceStateId 當(dāng)前狀態(tài)
* @param event 要觸發(fā)的事件
* @return 如果可以觸發(fā)則返回true,否則返回false
*/
boolean verify(S sourceStateId, E event);
/**
* 觸發(fā)事件并執(zhí)行狀態(tài)轉(zhuǎn)換
* @param sourceState 源狀態(tài)
* @param event 要觸發(fā)的事件
* @param ctx 上下文對(duì)象
* @return 轉(zhuǎn)換后的目標(biāo)狀態(tài)
*/
S fireEvent(S sourceState, E event, C ctx);
/**
* 觸發(fā)并行事件,返回多個(gè)目標(biāo)狀態(tài)
* @param sourceState 源狀態(tài)
* @param event 要觸發(fā)的事件
* @param ctx 上下文對(duì)象
* @return 轉(zhuǎn)換后的多個(gè)目標(biāo)狀態(tài)列表
*/
List<S> fireParallelEvent(S sourceState, E event, C ctx);
/**
* 獲取狀態(tài)機(jī)ID
* @return 狀態(tài)機(jī)唯一標(biāo)識(shí)符
*/
String getMachineId();
/**
* 顯示狀態(tài)機(jī)結(jié)構(gòu)
*/
void showStateMachine();
/**
* 生成PlantUML描述
* @return PlantUML格式的狀態(tài)機(jī)描述字符串
*/
String generatePlantUML();
}
關(guān)鍵方法解析
- verify():在實(shí)際觸發(fā)事件前驗(yàn)證轉(zhuǎn)換是否合法,避免無(wú)效的狀態(tài)轉(zhuǎn)換嘗試
- fireEvent():核心方法,處理單一路徑的狀態(tài)轉(zhuǎn)換
- fireParallelEvent():處理并行分支的狀態(tài)轉(zhuǎn)換,返回多個(gè)目標(biāo)狀態(tài)
- generatePlantUML():生成可視化描述,便于狀態(tài)機(jī)結(jié)構(gòu)的理解和調(diào)試
4.2 State和Transition接口
- State接口表示狀態(tài)機(jī)中的一個(gè)狀態(tài)節(jié)點(diǎn),管理從該狀態(tài)出發(fā)的所有轉(zhuǎn)換:
public interface State<S, E, C> extends Visitable {
/**
* 獲取狀態(tài)ID
* @return 狀態(tài)標(biāo)識(shí)符
*/
S getId();
/**
* 為狀態(tài)添加轉(zhuǎn)換規(guī)則
* @param event 觸發(fā)事件
* @param target 目標(biāo)狀態(tài)
* @param transitionType 轉(zhuǎn)換類(lèi)型
* @return 新創(chuàng)建的轉(zhuǎn)換對(duì)象
*/
Transition<S, E, C> addTransition(E event, State<S, E, C> target, TransitionType transitionType);
/**
* 獲取指定事件的所有轉(zhuǎn)換
* @param event 事件
* @return 轉(zhuǎn)換列表
*/
List<Transition<S, E, C>> getEventTransitions(E event);
/**
* 獲取該狀態(tài)的所有轉(zhuǎn)換
* @return 轉(zhuǎn)換集合
*/
Collection<Transition<S, E, C>> getAllTransitions();
}
- Transition接口表示從一個(gè)狀態(tài)到另一個(gè)狀態(tài)的轉(zhuǎn)換:
public interface Transition<S, E, C> {
/**
* 獲取源狀態(tài)
* @return 源狀態(tài)
*/
State<S, E, C> getSource();
/**
* 獲取觸發(fā)事件
* @return 事件
*/
E getEvent();
/**
* 獲取目標(biāo)狀態(tài)
* @return 目標(biāo)狀態(tài)
*/
State<S, E, C> getTarget();
/**
* 獲取轉(zhuǎn)換條件
* @return 條件對(duì)象
*/
Condition<C> getCondition();
/**
* 獲取轉(zhuǎn)換動(dòng)作
* @return 動(dòng)作對(duì)象
*/
Action<S, E, C> getAction();
/**
* 執(zhí)行狀態(tài)轉(zhuǎn)換
* @param ctx 上下文對(duì)象
* @param checkCondition 是否檢查條件
* @return 轉(zhuǎn)換后的目標(biāo)狀態(tài)
*/
State<S, E, C> transit(C ctx, boolean checkCondition);
}
4.3 狀態(tài)機(jī)工廠(chǎng)與構(gòu)建器
COLA提供了StateMachineBuilder和StateMachineFactory來(lái)簡(jiǎn)化狀態(tài)機(jī)的創(chuàng)建和管理:
// 創(chuàng)建狀態(tài)機(jī)構(gòu)建器
StateMachineBuilder<OrderState, OrderEvent, OrderContext> builder =
StateMachineBuilderFactory.create();
// 構(gòu)建狀態(tài)機(jī)
StateMachine<OrderState, OrderEvent, OrderContext> stateMachine =
builder.build(MACHINE_ID);
// 注冊(cè)狀態(tài)機(jī)
StateMachineFactory.register(stateMachine);
// 獲取狀態(tài)機(jī)實(shí)例
StateMachine<OrderState, OrderEvent, OrderContext> orderMachine =
StateMachineFactory.get(MACHINE_ID);
五、復(fù)雜業(yè)務(wù)流轉(zhuǎn)場(chǎng)景實(shí)現(xiàn)
5.1 條件分支與選擇轉(zhuǎn)換
在實(shí)際業(yè)務(wù)中,常常需要根據(jù)不同條件執(zhí)行不同的狀態(tài)轉(zhuǎn)換。例如,訂單支付后根據(jù)金額大小決定后續(xù)處理流程:
// 定義訂單金額閾值
BigDecimal VIP_THRESHOLD = new BigDecimal("1000");
// 已支付 -> 普通處理流程 (金額 < 1000)
builder.externalTransition()
.from(OrderState.PAID)
.to(OrderState.PROCESSING_NORMAL)
.on(OrderEvent.PROCESS)
.when(ctx -> ctx.getAmount().compareTo(VIP_THRESHOLD) < 0)
.perform(normalProcessingAction());
// 已支付 -> VIP處理流程 (金額 >= 1000)
builder.externalTransition()
.from(OrderState.PAID)
.to(OrderState.PROCESSING_VIP)
.on(OrderEvent.PROCESS)
.when(ctx -> ctx.getAmount().compareTo(VIP_THRESHOLD) >= 0)
.perform(vipProcessingAction());
上述代碼中,相同的PROCESS事件根據(jù)訂單金額觸發(fā)不同的狀態(tài)轉(zhuǎn)換,實(shí)現(xiàn)了條件分支邏輯。
5.2 并行分支與合并
某些業(yè)務(wù)場(chǎng)景需要從一個(gè)狀態(tài)同時(shí)轉(zhuǎn)換到多個(gè)狀態(tài),然后在后續(xù)步驟中合并。例如,訂單支付后同時(shí)觸發(fā)物流和財(cái)務(wù)兩個(gè)并行流程:
// 并行分支示例:支付后同時(shí)觸發(fā)物流和財(cái)務(wù)流程
builder.externalParallelTransition()
.from(OrderState.PAID)
.toAmong(OrderState.LOGISTICS_PROCESSING, OrderState.FINANCE_PROCESSING)
.on(OrderEvent.PROCESS)
.when(checkParallelCondition())
.perform(parallelProcessAction());
// 物流流程完成
builder.externalTransition()
.from(OrderState.LOGISTICS_PROCESSING)
.to(OrderState.LOGISTICS_COMPLETED)
.on(OrderEvent.LOGISTICS_DONE)
.perform(logisticsCompletedAction());
// 財(cái)務(wù)流程完成
builder.externalTransition()
.from(OrderState.FINANCE_PROCESSING)
.to(OrderState.FINANCE_COMPLETED)
.on(OrderEvent.FINANCE_DONE)
.perform(financeCompletedAction());
// 兩個(gè)并行流程都完成后合并
builder.externalTransitions()
.fromAmong(OrderState.LOGISTICS_COMPLETED, OrderState.FINANCE_COMPLETED)
.to(OrderState.ALL_PROCESSED)
.on(OrderEvent.MERGE)
.when(checkAllCompletedCondition())
.perform(mergeProcessAction());
觸發(fā)并行事件并處理結(jié)果:
// 觸發(fā)并行事件
List<OrderState> parallelStates = orderMachine.fireParallelEvent(
OrderState.PAID, OrderEvent.PROCESS, context);
// 輸出并行分支狀態(tài)
System.out.println("并行分支狀態(tài):");
for (OrderState state : parallelStates) {
System.out.println("- " + state);
}
// 輸出:
// 并行分支狀態(tài):
// - LOGISTICS_PROCESSING
// - FINANCE_PROCESSING
5.3 自循環(huán)與內(nèi)部轉(zhuǎn)換
內(nèi)部轉(zhuǎn)換(Internal Transition)是指不改變當(dāng)前狀態(tài)但執(zhí)行某些動(dòng)作的轉(zhuǎn)換,常用于狀態(tài)的自循環(huán)更新:
// 內(nèi)部轉(zhuǎn)換示例:訂單處理中超時(shí)提醒
builder.internalTransition()
.within(OrderState.PROCESSING)
.on(OrderEvent.REMIND)
.when(checkProcessingTimeCondition())
.perform(sendReminderAction());
觸發(fā)內(nèi)部轉(zhuǎn)換:
// 當(dāng)前狀態(tài)不變,但執(zhí)行提醒動(dòng)作
OrderState currentState = OrderState.PROCESSING;
OrderState newState = orderMachine.fireEvent(currentState, OrderEvent.REMIND, context);
System.out.println("訂單狀態(tài): " + newState); // 輸出: 訂單狀態(tài): PROCESSING
5.4 歷史狀態(tài)與子狀態(tài)機(jī)
對(duì)于復(fù)雜業(yè)務(wù)領(lǐng)域,可以將狀態(tài)機(jī)分層設(shè)計(jì),通過(guò)歷史狀態(tài)記錄和子狀態(tài)機(jī)實(shí)現(xiàn)更高級(jí)的狀態(tài)管理:
// 定義子狀態(tài)機(jī):退款流程
StateMachine<RefundState, RefundEvent, RefundContext> refundMachine = buildRefundSubMachine();
// 在主狀態(tài)機(jī)中引用子狀態(tài)機(jī)
builder.externalTransition()
.from(OrderState.PAID)
.to(OrderState.REFUND_PROCESSING)
.on(OrderEvent.REFUND)
.when(checkRefundCondition())
.perform(ctx -> {
// 調(diào)用子狀態(tài)機(jī)處理退款流程
RefundContext refundCtx = convertToRefundContext(ctx);
refundMachine.fireEvent(RefundState.INITIATED, RefundEvent.PROCESS, refundCtx);
});
六、可視化與調(diào)試
6.1 生成PlantUML狀態(tài)圖
COLA狀態(tài)機(jī)提供了generatePlantUML()方法,可以生成PlantUML格式的狀態(tài)圖描述,便于可視化和調(diào)試:
// 生成PlantUML描述
String plantUml = stateMachine.generatePlantUML();
System.out.println(plantUml);
- 生成的PlantUML描述可以通過(guò)PlantUML工具渲染為狀態(tài)圖,例如:
@startuml
[*] --> CREATED
CREATED --> PAID : PAY
CREATED --> CANCELLED : CANCEL
PAID --> SHIPPED : SHIP
SHIPPED --> DELIVERED : DELIVER
@enduml
上述描述渲染后將顯示完整的訂單狀態(tài)流轉(zhuǎn)圖。
6.2 狀態(tài)機(jī)結(jié)構(gòu)展示
通過(guò)showStateMachine()方法可以在控制臺(tái)打印狀態(tài)機(jī)結(jié)構(gòu):
stateMachine.showStateMachine();
- 輸出示例:
StateMachine: orderStateMachine
States:
CREATED
Transitions:
On: PAY, To: PAID, Type: EXTERNAL
On: CANCEL, To: CANCELLED, Type: EXTERNAL
PAID
Transitions:
On: SHIP, To: SHIPPED, Type: EXTERNAL
SHIPPED
Transitions:
On: DELIVER, To: DELIVERED, Type: EXTERNAL
DELIVERED
CANCELLED
七、性能優(yōu)化與最佳實(shí)踐
狀態(tài)機(jī)設(shè)計(jì)最佳實(shí)踐
- 狀態(tài)粒度控制:狀態(tài)劃分過(guò)細(xì)會(huì)增加復(fù)雜度,過(guò)粗則失去狀態(tài)機(jī)的優(yōu)勢(shì),需找到平衡點(diǎn)
- 單一職責(zé)原則:一個(gè)狀態(tài)機(jī)只負(fù)責(zé)一個(gè)業(yè)務(wù)領(lǐng)域的狀態(tài)流轉(zhuǎn)
- 事件命名規(guī)范:使用動(dòng)詞或動(dòng)詞短語(yǔ)命名事件(如PAY、SHIP),清晰表達(dá)觸發(fā)動(dòng)作
- 狀態(tài)命名規(guī)范:使用形容詞或過(guò)去分詞命名狀態(tài)(如PAID、SHIPPED),表示對(duì)象狀態(tài)
性能優(yōu)化技巧
- 狀態(tài)機(jī)復(fù)用:通過(guò)StateMachineFactory共享狀態(tài)機(jī)實(shí)例,避免重復(fù)創(chuàng)建
- 條件緩存:對(duì)于復(fù)雜且頻繁執(zhí)行的條件判斷,考慮添加緩存機(jī)制
- 異步處理:對(duì)于耗時(shí)的動(dòng)作,在Action中使用異步處理模式
- 狀態(tài)預(yù)加載:系統(tǒng)啟動(dòng)時(shí)預(yù)加載常用狀態(tài)機(jī),避免運(yùn)行時(shí)構(gòu)建開(kāi)銷(xiāo)
線(xiàn)程安全考量
COLA狀態(tài)機(jī)組件本身是線(xiàn)程安全的,可以在多線(xiàn)程環(huán)境下共享使用。但需要注意:
- 1.上下文對(duì)象(Context)可能被多個(gè)線(xiàn)程訪(fǎng)問(wèn),需要確保其線(xiàn)程安全性
- 2.Action中的業(yè)務(wù)邏輯應(yīng)避免共享可變狀態(tài),或采取適當(dāng)?shù)耐酱胧?br> *3. 并行觸發(fā)同一狀態(tài)機(jī)實(shí)例的不同事件是安全的,但同一業(yè)務(wù)對(duì)象的狀態(tài)轉(zhuǎn)換應(yīng)保證串行執(zhí)行
總結(jié)與展望
COLA狀態(tài)機(jī)組件通過(guò)StateMachine接口提供了一種優(yōu)雅的方式來(lái)處理復(fù)雜業(yè)務(wù)流轉(zhuǎn)邏輯,將傳統(tǒng)的if-else判斷轉(zhuǎn)換為清晰的狀態(tài)轉(zhuǎn)換規(guī)則,顯著提升了代碼的可讀性和可維護(hù)性。本文介紹的核心內(nèi)容包括:
- 狀態(tài)機(jī)的核心概念及COLA狀態(tài)機(jī)組件的架構(gòu)設(shè)計(jì)
- 使用StateMachine接口構(gòu)建基本狀態(tài)流轉(zhuǎn)的方法
- 處理?xiàng)l件分支、并行流程等復(fù)雜業(yè)務(wù)場(chǎng)景的技巧
- 狀態(tài)機(jī)的可視化調(diào)試和性能優(yōu)化策略
隨著業(yè)務(wù)復(fù)雜度的增長(zhǎng),狀態(tài)機(jī)模式的優(yōu)勢(shì)將更加明顯。未來(lái)可以進(jìn)一步探索狀態(tài)機(jī)與事件驅(qū)動(dòng)架構(gòu)(EDA)的結(jié)合,以及基于狀態(tài)機(jī)的業(yè)務(wù)流程自動(dòng)化。
通過(guò)將狀態(tài)機(jī)思想應(yīng)用到實(shí)際業(yè)務(wù)系統(tǒng)中,開(kāi)發(fā)團(tuán)隊(duì)可以構(gòu)建更加健壯、靈活且易于擴(kuò)展的業(yè)務(wù)流轉(zhuǎn)系統(tǒng),有效應(yīng)對(duì)復(fù)雜多變的業(yè)務(wù)需求。
參考:
https://gitcode.com/gh_mirrors/col/COLA
https://blog.csdn.net/gitblog_00735/article/details/151329646
https://blog.csdn.net/qq_40890575/article/details/129495003
https://segmentfault.com/a/1190000044529545