JavaScript状态模式

状态模式:

将对应的状态信息和状态变化保存在各自的类中,在主控制的类中,只需对所有的状态进行初始化即可,这样可一眼在构造函数中看出有多少种状态变化,避免了在主类中编写过多的if, else 条件语句来控制状态的变化,同时符合了代码的开放-封闭原则。

那么什么是状态?

状态在日常生活中很常见,比如看电视时遥控器的按钮对应着暂停和播放,第一次按下按钮暂停,再按下即播放。暂停和播放就是相应的状态。

最近买了电动牙刷,有这3种状态,开始按下即启动了默认模式 ,再次按下会变成敏感模式, 第三次按下即是关闭状态。如下图所示:

采用状态模式实现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
 class OffState {
constructor(toothbrush){
this.toothbrush = toothbrush;
}
clickButton() {
console.log('电动牙刷启动');
this.toothbrush.set(this.toothbrush.onState);
}
}
class OnState {
constructor(toothbrush){
this.toothbrush = toothbrush;
}
clickButton() {
console.log('刷牙模式切换为敏感模式');
this.toothbrush.set(this.toothbrush.sensitiveState);
}
}

class SensitiveState {
constructor(toothbrush){
this.toothbrush = toothbrush;
}
clickButton() {
console.log('电动牙刷关闭');
this.toothbrush.set(this.toothbrush.offState);
}
}

class ElecToothbrush {
constructor(){
this.onState = new OnState(this);
this.offState = new OffState(this);
this.sensitiveState = new SensitiveState(this);
this.curState = this.offState;
}

set(newState){
this.curState = newState;
}
}

var tb = new ElecToothbrush();

将tb实例上当前状态的clickButton事件绑定到button上,

1
2
<button onclick="tb.curState.clickButton()">开关</button>

打开控制台可以看见每按一次button,就会显示相应的状态变化。

如果不采用状态模式实现,那么在主类toothbrush中会有个click方法在切换对应的状态实现,就像下面这样会有很多if,else语句分支,如果未来再添加新的状态模式,则又需要添加相应的分支,之后该函数会变得越来越大,同时维护麻烦。

1
2
3
4
5
6
7
8
9
10
if(this.state==='off'){
console.log('牙刷启动默认模式');
this.state='on';
}else if(this.state==='on'){
console.log('sensitive mode');
this.state='senstive';
} else if(this.state === 'senstive'){
console.log('off');
this.state = 'off';
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!