设计模式-行为型-状态模式(State)
参考文献
状态模式
- 允许对象在其内部状态发生变化时改变其行为
组件
- 状态接口(
State Interface
):定义了表示各种状态的方法,具体状态类必须实现该接口. - 具体状态类(
Concrete State Class
):实现了状态接口的具体状态类,每个具体状态类负责处理特定的状态下的行为. - 上下文类(
Context Class
):维护一个对当前状态对象的引用,提供了用于切换状态和执行相应操作的方法.- 环境类状态切换方法(
Transition Methods in Context Class
):在上下文类中提供了用于切换状态的方法,允许客户端自行决定何时切换状态. - 共享状态(
Shared State
):多个上下文对象共享同一个状态对象的情况.这种情况下,可以将状态对象设计成可共享的,以减少对象的创建和内存占用.
- 环境类状态切换方法(
实现方式
-
定义状态接口(
State Interface
):创建一个表示状态的接口,其中包含了各种状态下的方法.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public abstract class CourseVideoState {
protected CourseVideoContext mCourseVideoContext;
public void setCourseVideoContext(CourseVideoContext courseVideoContext) {
mCourseVideoContext = courseVideoContext;
}
public abstract void play();
public abstract void speed();
public abstract void pause();
public abstract void stop();
} -
创建具体状态类(
Concrete State Class
):实现状态接口的具体状态类,每个具体状态类负责处理特定状态下的行为.- 将状态切换方法添加到上下文类中(
Optional
):如果需要客户端能够主动切换状态,可以在上下文类中添加相应的方法.
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98public class PauseState extends CourseVideoState {
public void play() {
super.mCourseVideoContext.setCourseVideoState(CourseVideoContext.PLAY_STATE);
}
public void speed() {
super.mCourseVideoContext.setCourseVideoState(CourseVideoContext.SPEED_STATE);
}
public void pause() {
System.out.println("课程视频已暂停");
}
public void stop() {
super.mCourseVideoContext.setCourseVideoState(CourseVideoContext.STOP_STATE);
}
}
public class PlayState extends CourseVideoState {
public void play() {
System.out.println("正常播放课程视频状态");
}
public void speed() {
super.mCourseVideoContext.setCourseVideoState(CourseVideoContext.SPEED_STATE);
}
public void pause() {
super.mCourseVideoContext.setCourseVideoState(CourseVideoContext.PAUSE_STATE);
}
public void stop() {
super.mCourseVideoContext.setCourseVideoState(CourseVideoContext.STOP_STATE);
}
}
public class SpeedState extends CourseVideoState {
public void play() {
super.mCourseVideoContext.setCourseVideoState(CourseVideoContext.PLAY_STATE);
}
public void speed() {
System.out.println("课程视频正在加速");
}
public void pause() {
super.mCourseVideoContext.setCourseVideoState(CourseVideoContext.PAUSE_STATE);
}
public void stop() {
super.mCourseVideoContext.setCourseVideoState(CourseVideoContext.STOP_STATE);
}
}
public class StopState extends CourseVideoState {
public void play() {
super.mCourseVideoContext.setCourseVideoState(CourseVideoContext.PLAY_STATE);
}
public void speed() {
System.out.println("ERROR 停止状态不能快进!!");
}
public void pause() {
System.out.println("ERROR 停止状态不能暂停!!");
}
public void stop() {
System.out.println("课程视频停止播放");
}
} - 将状态切换方法添加到上下文类中(
-
实现上下文类(
Context Class
):维护一个对当前状态对象的引用,并提供用于切换状态和执行相应操作的方法.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
35public class CourseVideoContext {
private CourseVideoState mCourseVideoState;
public final static PlayState PLAY_STATE = new PlayState();
public final static PauseState PAUSE_STATE = new PauseState();
public final static SpeedState SPEED_STATE = new SpeedState();
public final static StopState STOP_STATE = new StopState();
public CourseVideoState getCourseVideoState() {
return mCourseVideoState;
}
public void setCourseVideoState(CourseVideoState courseVideoState) {
mCourseVideoState = courseVideoState;
this.mCourseVideoState.setCourseVideoContext(this);
}
public void play() {
this.mCourseVideoState.play();
}
public void pause() {
this.mCourseVideoState.pause();
}
public void speed() {
this.mCourseVideoState.speed();
}
public void stop() {
this.mCourseVideoState.stop();
}
} -
在客户端代码中使用状态模式:创建上下文对象并调用不同状态下的方法,观察输出结果.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class Test {
public static void main(String[] args) {
CourseVideoContext courseVideoContext = new CourseVideoContext();
courseVideoContext.setCourseVideoState(new PlayState());
System.out.println("当前的状态:" + courseVideoContext.getCourseVideoState().getClass().getSimpleName());
courseVideoContext.pause();
System.out.println("当前的状态:" + courseVideoContext.getCourseVideoState().getClass().getSimpleName());
courseVideoContext.speed();
System.out.println("当前的状态:" + courseVideoContext.getCourseVideoState().getClass().getSimpleName());
courseVideoContext.stop();
System.out.println("当前的状态:" + courseVideoContext.getCourseVideoState().getClass().getSimpleName());
}
}
使用场景
- 如果对象需要根据自身当前状态进行不同行为, 同时状态的数量非常多且与状态相关的代码会频繁变更的话, 可使用状态模式.
- 如果某个类需要根据成员变量的当前值改变自身行为, 从而需要使用大量的条件语句时, 可使用该模式.
- 当相似状态和基于条件的状态机转换中存在许多重复代码时, 可使用状态模式.
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 HoleLin's Blog!