Skip to content
Jim Cowart edited this page Feb 2, 2015 · 2 revisions

machina.Fsm.extend and machina.BehavioralFsm.extend

Inspired by how backbone.js extends its objects, machina provides an extend method on the machina.BehavioralFsm and machina.Fsm constructor functions. This method call allows you to define, ahead of time, all of the metadata that you want passed to the constructor function, etc., so that all that is necessary to create an instance one you need one is to call new on the resulting 'extended' constructor function. You can continue to extend already-extended constructor functions as well, with each extension moving the 'base' objects into the prototype chain (in the order they were extended, etc.) While you should avoid deep inheritance hierarchies for other reasons, these facitilies allow you to easily specify base behavior that you may want all of your FSMs to share, and then build the specific FSMs from the original base FSM definition.

It's important to note that machina's extend call actually blends your FSM with the one you are extended. This means, for example, if the base FSM provides a states object, then the states from both will be merged into the resulting extended constructor function - the newer FSM definition will add or override handlers, as well as add any new states/handlers it declares, etc. (Note - "blended" states objects are instance-level, the prototype chain is not mutated.)

Example of extending an FSM constructor.

var BaseFsm = machina.Fsm.extend({
    initialize: function() {
        // do stuff here if you want to perform more setup work
        // this executes prior to any state transitions or handler invocations
    },
    states: {
        uninitialized: {
            start: function() {
                this.transition("first");
            }
        },
        first: {
            handlerA : function() {
                // do stuff
            }
        }
    }
});
// getting an instance from our extended constructor function above
var baseFsm = new BaseFsm();

// taking the BaseFsm constructor function and doing more
var ChildFsm = BaseFsm.extend({
    states: {
        uninitialized: {
            skipToTheEnd: function() {
                this.transition("second");
            }
        },
        first: {
            handlerA : function() {
                this.transition("second");
            }
            handlerB : function() {
                // do some work...
            }
        },
        second: {
            handlerC : function() {
                // do stuff
            }
        }
    }
});

// This instance will have a blending of BaseFsm and ChildFsm's states/handlers
var childFsm = new ChildFsm();