Most of the examples in this document construct a single state machine instance, such as:

  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'}}]);Copy the code

If you want to construct multiple instances with the same configuration, you should use a state machine factory. A state machine factory provides a JS constructor (for example: class) that can be instantiated multiple times:

  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
Copy the code

With factories, each state machine instance is a unique JS object. Each instance manages its own state property, but methods are shared through the normal JS stereotype mechanism.

Note: Pay attention to the handling of special cases. See data and state machine factories

Apply state machine behavior to existing objects

Sometimes you might want to apply the state machine behavior to an existing object (for example, the React component). This can be done using the statemachine.apply method:

  var component = { / *... * / };

  StateMachine.apply(component, {
    init: 'A'.transitions: {{name: 'step'.from: 'A'.to: 'B'}}});Copy the code

Be careful not to use state or transition action names that conflict with existing object properties.

Apply the state machine factory behavior to an existing class

State machine factory behavior can also be applied to existing classes, but must be initialized by calling this._fsm() in the class constructor method:

  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'
Copy the code