Javascript状态模式

javascript状态模式

状态模式是解决某些需求场景的最好方法。状态模式的关键是区分事物内部的状态,事物内部的状态的改变往往会带来事物的行为的改变
参考《javascript模式设计与开发实践》第16章

我在前面写了一个简单的教程,为了说明react/redux中的状态管理,《javascript模式设计与开发实践》里面有这样的模式。在下一步的重构中,如果从简单电灯的开关改为多级调光的电灯可以借鉴这样的模式。在简单的多个状态之间切换的时候,这样的模式是非常清晰的。

//两个状态之间的切换,使用if-else来切换,在有多个状态的时候,这样的切换就会嵌套很多的条件判断语句,如果加入新的状态,修改代码也比较困难
Light.prototype.buttonWasPressed = function(){
        if ( this.state === 'off' ){
            console.log( '开灯' );
            this.state = 'on';
        }else if ( this.state === 'on' ){
            console.log( '关灯' );
            this.state = 'off';
        }
    };

状态模式的关键就是:把事物的每种状态都封装成单独的类,跟此状态相关的行为都被封装在这个类的内部。只要有交互行为,只需要在上下文中,把这个请求委托给当前的状态对象即可,该状态对象会负责渲染它自身的行为。

  1. 封装状态
var OffLightState = function( light ){
           this.light = light;
           };
        
   OffLightState.prototype.buttonWasPressed = function(){
       console.log( '弱光' ); // offLightState 对应的行为
         this.light.setState( this.light.weakLightState ); // 切换状态到weakLightState
    };
   // WeakLightState:
   var WeakLightState = function( light ){
     this.light = light;
   };

   WeakLightState.prototype.buttonWasPressed = function(){
       console.log( '强光' ); // weakLightState 对应的行为
       this.light.setState( this.light.strongLightState ); // 切换状态到strongLightState
      };
   // StrongLightState:
     var StrongLightState = function( light ){
       this.light = light;
   };

    StrongLightState.prototype.buttonWasPressed = function(){
       console.log( '关灯' ); // strongLightState 对应的行为
       this.light.setState( this.light.offLightState ); // 切换状态到offLightState
   };
   ```
       
      
   

>在Light类中为每个状态类都创建一个状态对象,这样一来就可以很明显的看到电灯一共有多少个状态

var Light = function(){
    this.offLightState = new OffLightState( this );
    this.weakLightState = new WeakLightState( this );
    this.strongLightState = new StrongLightState( this );
    this.button = null;
};

>在button按钮被按下的时候,通过self.currState.buttonWasPressed()将请求委托为当前的状态去执行。

Light.prototype.init = function(){
var button = document.createElement( 'button' ),
self = this;
this.button = document.body.appendChild( button );
this.button.innerHTML = '开关';
this.currState = this.offLightState; // 设置当前状态
this.button.onclick = function(){
self.currState.buttonWasPressed();
}
};


最后提供一个setState的方法,状态对象通过这个方法来切换light对象的状态。状态对象的切换规律被定义在各个状态类中。

Light.prototype.setState = function( newState ){
this.currState = newState; //设置下一个状态
};


#####Javascript版本的状态机

var Light = function(){
this.currState = FSM.off; // 设置当前状态
this.button = null;
};

Light.prototype.init = function(){
    var button = document.createElement( 'button' ),
    self = this;
    button.innerHTML = '已关灯';
    this.button = document.body.appendChild( button );
    this.button.onclick = function(){
        //初始化下就是调用FSM.off的方法设置内部状态self.currState.buttonWasPressed.call( self ); // 把请求委托给FSM 状态机
    }
};
var FSM = {
    off: {
        buttonWasPressed: function(){
            console.log( '关灯' );
            this.button.innerHTML = '下一次按我是开灯';
            this.currState = FSM.on;
        }
    },
    on: {
        buttonWasPressed: function(){
            console.log( '开灯' );
            this.button.innerHTML = '下一次按我是关灯';
            this.currState = FSM.off;
        }
    }
};
var light = new Light();
light.init();

具体的实例详细看看书中的例子

推荐阅读更多精彩内容