状态机模式允许一个类在内部状态发生变化时更改其行为,仿佛它转变为另一个类一样。状态机模式与有限状态机密切相关。

通常的状态机实现随着类所能具有的状态数量增加而显著增加。状态机模式建议将所有所有模式转化为不同的类,并将所有与状态有关的操作封装在这些类当中。

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
class AudioPlayer {
public:
State* state;
Song* currentSong;
int volume;

AudioPlayer() {
state = new ReadyState(this);
}
~AudioPlayer() {
if (state) delete state;
}
void changeState(State* s) {
if (state) delete state;
state = s;
}
void clickLock() {
state->clickLock();
}
void clickPlay() {
state->clickPlay();
}
void clickNext() {
state->clickNext();
}
void clickPrevious() {
state->clickPrevious();
}
void startPlayback() {
// a service method independent of state
}
void stopPlayback() {
// ...
}
void previousSong() {
// ...
}
void fastForward(int time) {
// ...
}
void rewind(int time) {
// ...
}
// more service methods independent of state...
};

class State {
protected:
AudioPlayer* player;
public:
State(AudioPlayer* p): player(p) {}
virtual void clickLock() = 0;
virtual void clickPlay() = 0;
virtual void clickNext(std::string e) = 0;
virtual void clickPrevious(std::string e) = 0;
};

class ReadyState: public State {
void clickLock() override {
player->changeState(new LockedState(player));
}
void clickPlay() override {
player->changeState(new PlayingState(player));
}
void clickNext(std::string e) override {
player->nextSong();
}
void clickPrevious(std::string e) override {
player->previousSong();
}
};

class PlayingState: public State {
void clickLock() override {
player->changeState(new LockedState(player));
}
void clickPlay() override {
player->changeState(new ReadyState(player));
}
void clickNext(std::string e) override {
if (e == "doubleClick") player->nextSong();
else player->fastForward(5);
}
void clickPrevious(std::string e) {
if (e == "doubleClick") player->previous();
else player->rewind(5);
}
};