Edit in JSFiddle

(function(){
    var Events = {
        bind: function(){
            if(!this.o) this.o = $({});
            this.o.bind.apply(this.o, arguments);
        },
        trigger: function(){
            if(!this.o) this.o = $({});
            this.o.trigger.apply(this.o, arguments);
        }
    };
    
    var StateMachine = function(){};
    StateMachine.fn = StateMachine.prototype;
    $.extend(StateMachine.fn, Events);
    
    StateMachine.fn.add = function(controller){
        // this.o > events > changeに
        // コールバックがスタックされていく
        this.bind('change', function(e, current){
            // currentにはアクティブ化されたコントローラーが返って来る
            if(controller === current)
                // アクティブ化されたコントローラならアクティブに
                controller.activate();
            else
                // アクティブ化されたコントローラ以外ならディアクティブに
                controller.deactivate();
        });

        // それぞれのコントローラにイベントを紐付け、
        // 発火時には自身(コントローラ)を引数として渡す
        controller.active = $.proxy(function(){
            this.trigger('change', controller);
        }, this);
    };
    
    var con1 = {
        activate: function(){
            console.log('controller 1 activated');
        },
        deactivate: function(){
            console.log('controller 1 deactivated');
        }
    };
    
    var con2 = {
        activate: function(){
            console.log('controller 2 activated');
        },
        deactivate: function(){
            console.log('controller 2 deactivated');
        }
    };
    
    var sm = new StateMachine;
    sm.add(con1);
    sm.add(con2);

    con1.active();
    //con2.active();
}());

              

              

External resources loaded into this fiddle: