本文档中的大多数示例构造单个状态机实例,例如:
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' }
]
});
如果希望使用相同的配置构造多个实例,则应该使用状态机工厂。状态机工厂提供了一个js构造函数(例如:class
),它可以多次实例化:
var Matter = StateMachine.factory({ // <-- the factory is constructed here
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' }
]
});
var a = new Matter(), // <-- instances are constructed here
b = new Matter(),
c = new Matter();
b.melt();
c.melt();
c.vaporize();
a.state; // solid
b.state; // liquid
c.state; // gas
使用工厂,每个状态机实例都是唯一的js对象。每个实例都管理自己的state
属性,但是方法通过普通的js原型机制共享。
注意:注意特殊情况的处理。参看数据和状态机工厂
将状态机行为应用于现有对象
有时可能希望将状态机行为应用于已经存在的对象(例如,React组件)。可以通过StateMachine.apply
方法来完成:
var component = { /* ... */ };
StateMachine.apply(component, {
init: 'A',
transitions: {
{ name: 'step', from: 'A', to: 'B' }
}
});
注意不要使用与现有对象属性冲突的状态或转换动作名称。
将状态机工厂行为应用于现有类
还可以将状态机工厂行为应用于现有类,但必须通过在类构造函数方法中调用this._fsm()
来初始化:
function Person(name) {
this.name = name;
this._fsm(); // <-- IMPORTANT
}
Person.prototype = {
speak: function() {
console.log('my name is ' + this.name + ' and I am ' + this.state);
}
}
StateMachine.factory(Person, {
init: 'idle',
transitions: {
{ name: 'sleep', from: 'idle', to: 'sleeping' },
{ name: 'wake', from: 'sleeping', to: 'idle' }
}
});
var amy = new Person('amy'),
bob = new Person('bob');
bob.sleep();
amy.state; // 'idle'
bob.state; // 'sleeping'
amy.speak(); // 'my name is amy and I am idle'
bob.speak(); // 'my name is bob and I am sleeping'