状态机是由一组状态(states), 如:
- solid
- liquid
- gas
和一套转换动作(transitions)组成的, 如:
- melt
- freeze
- vaporize
- condense
var fsm = new StateMachine({
init: 'solid',
transitions: [
{ name: 'melt', from: 'solid', to: 'liquid' },
{ name: 'freeze', from: 'liquid', to: 'solid' },
{ name: 'vaporize', from: 'liquid', to: 'gas' },
{ name: 'condense', from: 'gas', to: 'liquid' }
]
});
fsm.state; // 'solid'
fsm.melt();
fsm.state; // 'liquid'
fsm.vaporize();
fsm.state; // 'gas'
一个转换动作处理多个状态
如果多个状态转换都要用相同的转换动作,那么就把name值设置为相同的动作命名。
{ name: 'step', from: 'A', to: 'B' },
{ name: 'step', from: 'B', to: 'C' },
{ name: 'step', from: 'C', to: 'D' }
如果多个from
状态都要转换到相同的to
状态, 如:
{ name: 'reset', from: 'B', to: 'A' },
{ name: 'reset', from: 'C', to: 'A' },
{ name: 'reset', from: 'D', to: 'A' }
可以将from
状态组成数组来对其进行缩写:
{ name: 'reset', from: [ 'B', 'C', 'D' ], to: 'A' }
将以上用法合并成一个简单示例如下:
var fsm = new StateMachine({
init: 'A',
transitions: [
{ name: 'step', from: 'A', to: 'B' },
{ name: 'step', from: 'B', to: 'C' },
{ name: 'step', from: 'C', to: 'D' },
{ name: 'reset', from: [ 'B', 'C', 'D' ], to: 'A' }
]
})
此示例将创建一个具有两个转换方法的对象:
fsm.step()
fsm.reset()
reset
方法总是将状态转换到A
状态, 而step
转换到的目标状态为当前状态对应的状态结束。
通配符转换
如何适用于从任何状态转换到目标状态?可以在from
状态中使用通配符*
。
var fsm = new StateMachine({
transitions: [
// ...
{ name: 'reset', from: '*', to: 'A' }
]
});
条件转换
通过提供一个函数作为to属性,可以实现在运行时选择目标状态:
var fsm = new StateMachine({
init: 'A',
transitions: [
{ name: 'step', from: '*', to: function(n) { return increaseCharacter(this.state, n || 1) } }
]
});
fsm.state; // A
fsm.step();
fsm.state; // B
fsm.step(5);
fsm.state; // G
// helper method to perform (c = c + n) on the 1st character in str
function increaseCharacter(str, n) {
return String.fromCharCode(str.charCodeAt(0) + n);
}
allStates
方法只有在运行到这个条件状态时才包含它们:
fsm.state; // A
fsm.allStates(); // [ 'A' ]
fsm.step();
fsm.state; // B
fsm.allStates(); // [ 'A', 'B' ]
fsm.step(5);
fsm.state; // G
fsm.allStates(); // [ 'A', 'B', 'G' ]
GOTO - 任意切换状态
你可以使用条件转换,组合from
使用通配符,来实现任意goto行为:
var fsm = new StateMachine({
init: 'A'
transitions: [
{ name: 'step', from: 'A', to: 'B' },
{ name: 'step', from: 'B', to: 'C' },
{ name: 'step', from: 'C', to: 'D' },
{ name: 'goto', from: '*', to: function(s) { return s } }
]
})
fsm.state; // 'A'
fsm.goto('D');
fsm.state; // 'D'
一套完整的生命周期事件在使用时仍然适用goto。