Javascript-设计模式_状态模式
前言
状态模式的关键是区分事物内部的状态,事物内部状态的改变往往会带来事物的行为改变,即对象行为是基于状态来改变的,内部的状态转化,导致了行为表现形式不同
当电灯开着,此时按下开关,电灯会切换到关闭状态;再按一次开关,电灯又将被打开。同一个开关在不同的状态下,表现出来的行为是不一样的
场景条件--有限状态机
-
状态总数(state)是有限的
-
任一时刻,只处在一种状态之中
-
某种条件下,会从一种状态转变(transition)到另一种状态
允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类
解释:
-
将状态封装成独立的类,并将请求委托给当前的状态对象,当对象的内部状态发生改变时,会带来不同的行为变化
-
使用的对象,在不同的状态下具有截然不同的行为(委托效果)
谈到封装,一般优先考虑封装对象的行为,而不是对象的状态,但在状态模式中刚好相反,状态模式的关键是把事物的每种状态都封装成单独的类
示例
点灯程序 (弱光 –> 强光 –> 关灯)循环
/* 关灯 */
const OffLightState = light => {
this.light = light
}
/* 弱光 */
const WeakLightState = light => {
this.light = light
}
/* 强光 */
const StrongLightState = light => {
this.light = light
}
const Light = () => {
// 开关状态
this.offLight = new OffLightState(this)
this.weakLight = new WeakLightState(this)
this.strongLight = new StrongLightState(this)
// 快关按钮
this.button = null
}
Light.prototype.init = () => {
const button = document.createElement('button')
const self = this
this.button = document.body.appendChild(button)
this.button.innerHTML = '开关'
this.currentState = this.offLight
this.button.click = () => {
self.currentState.buttonWasPressed()
}
}
/* 让抽象父类的抽象方法直接抛出一个异常(避免状态子类未实现buttonWasPressed方法) */
Light.prototype.buttonWasPressed = () => {
throw new Error('父类的buttonWasPressed方法必须被重写')
}
Light.prototype.setState = newState => {
this.currentState = newState
}
/* 关灯 */
OffLightState.prototype = new Light() // 继承抽象类
OffLightState.prototype.buttonWasPressed = () => {
console.log('关灯!')
this.light.setState(this.light.weakLight)
}
/* 弱光 */
WeakLightState.prototype = new Light()
WeakLightState.prototype.buttonWasPressed = () => {
console.log('弱光!')
this.light.setState(this.light.strongLight)
}
/* 强光 */
StrongLightState.prototype = new Light()
StrongLightState.prototype.buttonWasPressed = () => {
console.log('强光!')
this.light.setState(this.light.offLight)
}
性能优化点
-
如何管理状态对象的创建和销毁
第一种仅当state对象被需要时才创建并随后销毁(state对象比较庞大,优先选择)
另一种是一开始就创建好所有的状态对象,并且始终不销毁它们(状态改变频繁)
-
利用享元模式共享一个state对象
优缺点
优点
封装了转化规则,对于大量分支语句,可以考虑使用状态类进一步封装。 每个状态都是确定的,所以对象行为是可控的
缺点
状态模式的关键是将事物的状态都封装成单独的类,这个类的各种方法就是“此种状态对应的表现行为”, 因此状态类会增加程序开销
总结
状态模式的使用场景也特别明确,有如下两点
-
一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为
-
一个操作中含有大量的分支语句,而且这些分支语句依赖于该对象的状态。状态通常为一个或多个枚举常量的表示
简而言之,当遇到很多同级 if-else或者 switch的时候,可以使用状态模式来进行简化

浙公网安备 33010602011771号