状态模式的关键是区分事物内部的状态,事物内部状态的改变每每会带来事物的行为改变。设计模式
咱们来想象这样一个场景:有一个电灯,电灯上面只有一个开关。当电灯开着的时候,此时 按下开关,电灯会切换到关闭状态;再按一次开关,电灯又将被打开。同一个开关按钮,在不一样 的状态下,表现出来的行为是不同的bash
var Light = function(){
this.state = 'off'; // 给电灯设置初始状态 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(){
self.buttonWasPressed();
}
};
Light.prototype.buttonWasPressed = function(){
if ( this.state === 'off' ){
console.log( '开灯' );
this.state = 'on';
} else if ( this.state === 'on' ){
console.log( '关灯' );
this.state = 'off';
}
};
var light = new Light();
light.init();
复制代码
假如如今电灯的状态多了一种,第一次按下打开弱光,第二次按下打开强光,第三次才是关闭电灯。以上的代码就没法知足这种电灯的状况app
状态模式的关键是把事物的 每种状态都封装成单独的类,跟此种状态有关的行为都被封装在这个类的内部,因此 button 被按下的的时候,只须要在上下文中,把这个请求委托给当前的状态对象便可,该状态对象会负责渲染它自身的行为。以下图所示post
/******************** 定义 3 个状态类 ************************/
// OffLightState:
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;
};
/******************** 提供一个 方法来切换 light 对象的状态 ************************/
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();
}
};
Light.prototype.setState = function( newState ){
this.currState = newState;
};
var light = new Light();
light.init();
复制代码
执行结果跟以前的代码一致,可是使用状态模式的好处很明显,它可使每 一种状态和它对应的行为之间的关系局部化,这些行为被分散和封装在各自对应的状态类之中, 便于阅读和管理代码。 另外,状态之间的切换都被分布在状态类内部,这使得咱们无需编写过多的 if、else 条件 分支语言来控制状态之间的转换。this