状态机是一种用来描述系统在不同状态下,根据外部输入或内部事件触发,按照预设规则进行状态切换的抽象模型。它把系统的行为拆解为有限个明确的状态,以及状态之间的转换条件,让复杂的流程逻辑变得清晰可维护。有限状态机是状态机中最常用的类型,它的状态总数是有限的,每个状态都有明确的进入、退出逻辑和对应的转换规则。

有限状态机的核心组成
一个完整的有限状态机通常包含以下四个核心部分:
- 状态集合:系统所有可能处于的状态,状态数量必须是有限的。
- 初始状态:系统启动后默认进入的第一个状态。
- 输入集合:所有可能触发状态转换的事件或输入参数。
- 转换规则:定义从某个状态接收到某个输入后,会切换到哪个新状态,以及是否需要执行对应的动作。
简单场景示例说明
我们可以用一个订单流程的场景来理解有限状态机,订单的状态集合可以是待支付、已支付、已发货、已完成、已取消,初始状态是待支付。当待支付状态下接收到支付成功的输入,就会转换到已支付状态;已支付状态下接收到发货的输入,就会转换到已发货状态,以此类推。每个状态转换都可以绑定对应的业务逻辑,比如支付成功后扣减库存,发货后更新物流信息等。
JavaScript实现有限状态机
下面用JavaScript实现一个简单的订单状态机,包含状态定义、转换规则配置和状态切换方法:
// 定义订单状态集合
const OrderState = {
WAIT_PAY: 'wait_pay',
PAID: 'paid',
SHIPPED: 'shipped',
FINISHED: 'finished',
CANCELED: 'canceled'
};
// 定义转换规则,key为当前状态,value为输入对应的下一个状态和动作
const transitionMap = {
[OrderState.WAIT_PAY]: {
pay: { nextState: OrderState.PAID, action: () => console.log('支付成功,扣减库存') },
cancel: { nextState: OrderState.CANCELED, action: () => console.log('订单取消,释放库存') }
},
[OrderState.PAID]: {
ship: { nextState: OrderState.SHIPPED, action: () => console.log('订单发货,更新物流信息') },
refund: { nextState: OrderState.CANCELED, action: () => console.log('订单退款,恢复库存') }
},
[OrderState.SHIPPED]: {
confirm: { nextState: OrderState.FINISHED, action: () => console.log('订单确认完成,交易结束') }
}
};
// 有限状态机类
class FiniteStateMachine {
constructor(initialState) {
this.currentState = initialState;
}
// 触发输入,执行状态转换
handleInput(input) {
const currentRules = transitionMap[this.currentState];
if (!currentRules || !currentRules[input]) {
console.log(`当前状态${this.currentState}不支持输入${input}`);
return;
}
const { nextState, action } = currentRules[input];
// 执行转换前的动作
action();
// 更新当前状态
this.currentState = nextState;
console.log(`状态已切换到:${this.currentState}`);
}
}
// 使用示例
const orderFsm = new FiniteStateMachine(OrderState.WAIT_PAY);
orderFsm.handleInput('pay'); // 支付成功,扣减库存 状态已切换到:paid
orderFsm.handleInput('ship'); // 订单发货,更新物流信息 状态已切换到:shipped
orderFsm.handleInput('confirm'); // 订单确认完成,交易结束 状态已切换到:finished
Python实现有限状态机
同样的逻辑也可以用Python实现,结构更加清晰,适合后端业务逻辑使用:
# 定义订单状态常量
class OrderState:
WAIT_PAY = "wait_pay"
PAID = "paid"
SHIPPED = "shipped"
FINISHED = "finished"
CANCELED = "canceled"
# 定义有限状态机类
class FiniteStateMachine:
def __init__(self, initial_state):
self.current_state = initial_state
# 定义转换规则,格式为 {当前状态: {输入: (下一个状态, 动作函数)}}
self.transition_map = {
OrderState.WAIT_PAY: {
"pay": (OrderState.PAID, self._pay_action),
"cancel": (OrderState.CANCELED, self._cancel_action)
},
OrderState.PAID: {
"ship": (OrderState.SHIPPED, self._ship_action),
"refund": (OrderState.CANCELED, self._refund_action)
},
OrderState.SHIPPED: {
"confirm": (OrderState.FINISHED, self._confirm_action)
}
}
def _pay_action(self):
print("支付成功,扣减库存")
def _cancel_action(self):
print("订单取消,释放库存")
def _ship_action(self):
print("订单发货,更新物流信息")
def _refund_action(self):
print("订单退款,恢复库存")
def _confirm_action(self):
print("订单确认完成,交易结束")
def handle_input(self, input_event):
current_rules = self.transition_map.get(self.current_state, {})
if input_event not in current_rules:
print(f"当前状态{self.current_state}不支持输入{input_event}")
return
next_state, action = current_rules[input_event]
# 执行转换动作
action()
# 更新状态
self.current_state = next_state
print(f"状态已切换到:{self.current_state}")
# 使用示例
if __name__ == "__main__":
order_fsm = FiniteStateMachine(OrderState.WAIT_PAY)
order_fsm.handle_input("pay")
order_fsm.handle_input("ship")
order_fsm.handle_input("confirm")
有限状态机的适用场景
有限状态机适合处理状态明确、转换规则固定的场景,比如:
- 游戏角色的状态控制,比如待机、移动、攻击、死亡等状态切换。
- 业务流程引擎,比如审批流程、订单流程、工单流程等。
- 网络协议解析,比如TCP连接的状态管理、自定义协议的帧解析。
- UI组件的状态管理,比如按钮的禁用、加载、正常状态切换。
当业务中的状态数量较多、转换逻辑复杂时,使用有限状态机可以让代码结构更清晰,后续修改状态规则时只需要调整转换配置,不需要修改核心的状态切换逻辑,降低维护成本。