Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 74d2fc0

Browse files
✨ feat: 添加状态模式
1 parent 8d62bb6 commit 74d2fc0

File tree

3 files changed

+239
-0
lines changed

3 files changed

+239
-0
lines changed

‎State/State.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<meta http-equiv="X-UA-Compatible" content="ie=edge">
7+
<title>状态模式</title>
8+
</head>
9+
<body>
10+
<script src="State.js"></script>
11+
</body>
12+
</html>

‎State/State.js

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// class Light {
2+
// constructor() {
3+
// this.state = 'off'; //电灯默认为关闭状态
4+
// this.button = null;
5+
// }
6+
7+
// init() {
8+
// let button = document.createElement('button');
9+
// let self = this;
10+
// button.innerHTML = '我是开关';
11+
// this.button = document.body.appendChild(button);
12+
// this.button.onclick = () => {
13+
// self.buttonWasClicked();
14+
// }
15+
// }
16+
17+
// buttonWasClicked() {
18+
// if (this.state === 'off') {
19+
// console.log('开灯');
20+
// this.state = 'on';
21+
// } else {
22+
// console.log('关灯');
23+
// this.state = 'off';
24+
// }
25+
// }
26+
// }
27+
28+
// let light = new Light();
29+
// light.init();
30+
31+
32+
33+
// 定义三个不同的状态类
34+
// 灯未开启的状态
35+
class OffLightState {
36+
constructor(light) {
37+
this.light = light;
38+
}
39+
40+
buttonWasClicked() {
41+
console.log('切换到弱光模式');
42+
this.light.setState(this.light.weakLightState);
43+
}
44+
}
45+
46+
// 弱光状态
47+
class WeakLightState {
48+
constructor(light) {
49+
this.light = light;
50+
}
51+
52+
buttonWasClicked() {
53+
console.log('切换到强光模式');
54+
this.light.setState(this.light.strongLightState);
55+
}
56+
}
57+
58+
// 强光状态
59+
class StrongLightState {
60+
constructor(light) {
61+
this.light = light;
62+
}
63+
64+
buttonWasClicked() {
65+
console.log('关灯');
66+
this.light.setState(this.light.offLightState);
67+
}
68+
}
69+
70+
class Light {
71+
constructor() {
72+
this.offLightState = new OffLightState(this);
73+
this.weakLightState = new WeakLightState(this);
74+
this.strongLightState = new StrongLightState(this);
75+
this.button = null;
76+
}
77+
78+
init() {
79+
let button = document.createElement('button');
80+
let self = this;
81+
button.innerHTML = '我是开关';
82+
this.button = document.body.appendChild(button);
83+
this.curState = this.offLightState;
84+
this.button.onclick = () => {
85+
self.curState.buttonWasClicked();
86+
}
87+
}
88+
89+
setState(state) {
90+
this.curState = state;
91+
}
92+
}
93+
94+
let light = new Light();
95+
light.init();

‎State/State.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# 状态模式
2+
3+
> 状态模式允许一个对象在其内部状态改变时改变行为,这个对象看上去像改变了类一样,但其实并没有。状态模式把所研究对象在其内部状态改变时,其行为也随之改变,状态模式需要对每一个系统可能取得的状态创立一个状态类的子类。当系统的状态变化时,系统改变所选的子类。
4+
5+
假设我们此时有一个电灯,在电灯上有个开关,在灯未亮时按下使灯开启,在灯已亮时按下则将灯关闭,此时行为表现时不一样的:
6+
7+
```javascript
8+
class Light {
9+
constructor() {
10+
this.state = 'off'; //电灯默认为关闭状态
11+
this.button = null;
12+
}
13+
14+
init() {
15+
let button = document.createElement('button');
16+
let self = this;
17+
button.innerHTML = '我是开关';
18+
this.button = document.body.appendChild(button);
19+
this.button.onclick = () => {
20+
self.buttonWasClicked();
21+
}
22+
}
23+
24+
buttonWasClicked() {
25+
if (this.state === 'off') {
26+
console.log('开灯');
27+
this.state = 'on';
28+
} else {
29+
console.log('关灯');
30+
this.state = 'off';
31+
}
32+
}
33+
}
34+
35+
let light = new Light();
36+
light.init();
37+
```
38+
39+
[![uD8U1A.gif](https://s2.ax1x.com/2019/10/04/uD8U1A.gif)](https://imgchr.com/i/uD8U1A)
40+
41+
此时只有两种状态,我们尚且可以不使用状态模式,但当状态较多时,例如,当电灯出现弱光,强光档位时,以上的代码就无法满足需求。
42+
43+
### ### 使用状态模式重构
44+
45+
状态模式的关键是把每种状态都封装成单独的类,跟此种状态有关的行为都被封装在这个类的内部,在按钮被按下时,只需要在上下文中,把这个请求委托给当前状态对象即可,该状态对象会负责渲染它自身的行为。
46+
47+
首先定义三种不同状态的类
48+
49+
```javascript
50+
// 灯未开启的状态
51+
class OffLightState {
52+
constructor(light) {
53+
this.light = light;
54+
}
55+
56+
buttonWasClicked() {
57+
console.log('切换到弱光模式');
58+
this.light.setState(this.light.weakLightState);
59+
}
60+
}
61+
62+
// 弱光状态
63+
class WeakLightState {
64+
constructor(light) {
65+
this.light = light;
66+
}
67+
68+
buttonWasClicked() {
69+
console.log('切换到强光模式');
70+
this.light.setState(this.light.strongLightState);
71+
}
72+
}
73+
74+
// 强光状态
75+
class StrongLightState {
76+
constructor(light) {
77+
this.light = light;
78+
}
79+
80+
buttonWasClicked() {
81+
console.log('关灯');
82+
this.light.setState(this.light.offLightState);
83+
}
84+
}
85+
```
86+
87+
接着我们改写 Light 类,在内部通过`curState`记录当前状态
88+
89+
```javascript
90+
class Light {
91+
constructor() {
92+
this.offLightState = new OffLightState(this);
93+
this.weakLightState = new WeakLightState(this);
94+
this.strongLightState = new StrongLightState(this);
95+
this.button = null;
96+
}
97+
98+
init() {
99+
let button = document.createElement('button');
100+
let self = this;
101+
button.innerHTML = '我是开关';
102+
this.button = document.body.appendChild(button);
103+
this.curState = this.offLightState;
104+
this.button.onclick = () => {
105+
self.curState.buttonWasClicked();
106+
}
107+
}
108+
109+
setState(state) {
110+
this.curState = state;
111+
}
112+
}
113+
```
114+
115+
之后实例化对象后,我们在页面中查看
116+
117+
```javascript
118+
let light = new Light();
119+
light.init();
120+
```
121+
122+
123+
124+
[![uDGh2d.gif](https://s2.ax1x.com/2019/10/04/uDGh2d.gif)](https://imgchr.com/i/uDGh2d)
125+
126+
127+
128+
## 总结
129+
130+
- 状态模式通过定义不同的状态类,根据状态的改变而改变对象的行为。
131+
- 不必把大量的逻辑都写在被操作的对象的类中,很容易增加新的状态。
132+
- 符合开放-封闭原则。

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /