State Pattern4


State Pattern1 : C++ State patternÀ» ÀÚ¹Ù½ºÅ©¸³Æ®·Î º¯È¯
State Pattern2: »óÅ º¯È¯ Å×À̺í
State Pattern3: ÀÚ¹Ù½ºÅ©¸³Æ® ´Ù¿òÀÇ »óÅÂÆÐÅÏ

»óÅ º¯È¯ Å×À̺í°ú ÀÚ¹Ù½ºÅ©¸³Æ® »óÅÂÆÐÅÏÀ» ÇÕÃÄ º¸ÀÚ.

¾ÕÀå¿¡¼­µµ ¼³¸í ÇßÁö¸¸ ´Ù½Ã Çѹø ¼³¸í ÇÑ´Ù.

changeStateKey ÇÔ¼ö : stateObj Å×ÀÌºí¿¡¼­ name º¯È¯Å°¸¦ °¡Áø À̸§ÀÌ ÀÖ´ÂÁö üũÇÑ´Ù.
¿©±â¼­ stateObj´Â actTable·Î »óÅÂÀÇ À̸§ Å×À̺íÀÌ´Ù.

getFsm ÇÔ¼ö : changeStateKey·Î ±¸ÇÑ Å°¸¦ ÀÌ¿ëÇØ »óÅ ¿ÀºêÁ§Æ®¸¦ ¸®ÅÏÇÑ´Ù.
                   ¿©±â¼­´Â RunÀ̳ª Walk »óŸ¦ ¸®ÅÏ ÇÒ °ÍÀÌ´Ù.

»ç¿ë ¹æ¹ý)

_stateManager.setState( getFsm('walk2Run', actTable)());   

getFsm(  )ÇÔ¼ö·Î »óŸ¦ ±¸Çؼ­ ÇÔ¼ö¸¦ ½ÇÇàÇÏ¸é »óÅ°¡ »ý¼ºµÈ´Ù.
»óÅ´ RunÀ̳ª Walk µÑÁß¿¡ ÇϳªÀÌ´Ù.

window.addEventListener('DOMContentLoaded', function(){
    appMain.init();
});

const changeStateKey = function (name, stateObj) {
    const state = stateObj.currentState;

    if (stateObj.transition[state][name]) {
        stateObj.currentState = stateObj.transition[state][name];
        console.log(`${state} + ${name} --> ${stateObj.currentState}`);
        return stateObj.currentState;
    }
    else {
        console.error(`can't change currentState:${state} --> command:${name}`);  
        return false;
    }
}

const getFsm = function (name, stateObj) {
    let key = changeStateKey(name, stateObj);
    if(!key)
        return key;
    
    if(!stateObj.state.hasOwnProperty(key))
        return false;
        
    return stateObj.state[key];
}

var StateManager = function(){
    var proto =  StateManager.prototype;

    function StateManager(){
        this.prevStae = null;
        this.state = null;
    }

    proto.setState = function(newState){
        if(this.state && this.state.exit)
            this.state.exit();
        this.state = newState;
        if(this.state.enter)
            this.state.enter();
    };
   
    proto.execute = function(){
        if(this.state === null)
            return;
        this.state.execute();
    };

    return new StateManager();
};

var appMain = (function () {   
    var _stateManager = StateManager();

    var Walk = function(){
        var proto = Walk.prototype;
        function Walk(){}

        proto.execute = function(){
            console.log('walk execute');
        };
         
        return new Walk();
    };
    
    var Run = function(){
        var proto = Run.prototype;
        function Run(){}

        proto.enter = function(){
            console.log('Run enter');
        };        
              
        proto.execute = function(){
            console.log('Run execute');
        };

        proto.exit = function(){
            console.log('Run exit');
        };        
        return new Run();
    };    
    
    function init(){
        console.log('appMain init');
        _stateManager.setState(actTable.state['walk']());
        _stateManager.execute();
        _stateManager.setState( getFsm('walk2Run', actTable)());    
        _stateManager.execute();
        _stateManager.setState( getFsm('run2walk', actTable)());            
        _stateManager.execute();
    }
    
    //¸¶Áö¸· ºÎºÐ¿¡ µÎ´Â°ÍÀÌ ÁÁ´Ù. ù ºÎºÐ¿¡ µÎ¸é Walk, Run ÇÔ¼ö°¡ undefined µÉ¼öµµ ÀÖ´Ù.
    const actTable = {
        currentState: 'walk',
        transition: {
            'walk': {
                walk2Run: 'run'
            },
            'run': {
                run2walk: 'walk',
            }
        },
        state: {
            'walk': Walk,
            'run': Run
        }
    };
    
    return {
        init: init,
    };
})();

½ÇÇà °á°ú)
appMain init
walk execute
walk + walk2Run --> run
Run enter
Run execute
run + run2walk --> walk
walk execute

´Ù¿î·Îµå : statePattern4.html