状态设计模式

什么是状态设计模式

类图如下:
状态设计模式

这个可以理解为对象行为随着状态改变的一个设计模式

如,随着四季变化,树的行为也跟着变化。

随着开关的变化,灯泡的行为也跟着变化。

为什么要使用

在软件设计过程中,对象的状态可能是会发生改变的,当对象的状态改变之后,我们可以使用 if 或者 switch 语句来判断对象的行为,但是如果对象的状态特别多的话,就会发生一个问题,对象的状态增加修改之后会频繁修改原来的类。

使用状态设计模式时,允许一个对象在其内部状态改变时改变它的行为。

类型

行为型模式

参与者

  • Context 上下文类

    • 维护一个具体状态角色ConcreteState的实例,这个实例定义当前状态。
  • IState 抽象状态类

    • 声明了各种不同状态对应的方法。
  • ConcreteState 具体状态类

    • 每一个实现一个与Context的一个状态相关的行为。

例子

只有两种状态的灯泡

代码中 Light 代表 Context 上下文类

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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<?php

/**
* 只有两种状态的灯泡,可以开启和关闭
*/

/**
* 灯
*/
class Light
{
private $offState;
private $onState;

/**
* @var IState
*/
private $currentState;

public function __construct()
{
$this->offState = new offState($this);
$this->onState = new onState($this);
$this->currentState = $this->offState;
}

public function turnOn()
{
$this->currentState->turnOn();
}

public function turnOff()
{
$this->currentState->turnOff();
}

public function setState(IState $state)
{
$this->currentState = $state;
}

public function getOnState()
{
return $this->onState;
}

public function getOffState()
{
return $this->offState;
}
}

interface IState
{
public function turnOn();

public function turnOff();
}

/**
* 灯的关闭状态
*/
class offState implements IState
{
private $context;

public function __construct(Light $light)
{
$this->context = $light;
}

public function turnOff()
{
echo 'light is already **off**, please chose another operation'.PHP_EOL;
}

public function turnOn()
{
echo 'light on!'.PHP_EOL;
$this->context->setState($this->context->getOnState());
}
}

/**
* 灯的开启状态
*/
class onState implements IState
{
private $context;

public function __construct(Light $light)
{
$this->context = $light;
}

public function turnOff()
{
echo 'light off!'.PHP_EOL;
$this->context->setState($this->context->getOffState());
}

public function turnOn()
{
echo 'light is already **on**, please chose another operation'.PHP_EOL;
}
}

class Client
{
private $light;

public function __construct()
{
$this->light = new Light();
$this->light->turnOn();
$this->light->turnOn();
$this->light->turnOff();
$this->light->turnOff();
}
}

$client = new Client();

新增加一种损坏状态

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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
<?php

// 状态模式设计方法

/**
* 灯
*/
class Light
{
private $offState;
private $onState;
private $brokenState;

/**
* @var IState
*/
private $currentState;

public function __construct()
{
$this->offState = new offState($this);
$this->onState = new onState($this);
$this->brokenState = new brokenState();
$this->currentState = $this->offState;
}

public function turnOn()
{
$this->currentState->turnOn();
}

public function turnOff()
{
$this->currentState->turnOff();
}

public function brokeIt()
{
$this->currentState->turnBroken();
}

public function setState(IState $state)
{
$this->currentState = $state;
}

public function getOnState()
{
return $this->onState;
}

public function getOffState()
{
return $this->offState;
}

public function getBrokeState()
{
return $this->brokenState;
}
}

interface IState
{
public function turnOn();

public function turnOff();

public function turnBroken();
}

/**
* 灯的关闭状态
*/
class offState implements IState
{
private $context;

public function __construct(Light $light)
{
$this->context = $light;
}

public function turnOff()
{
echo 'light is already **off**, please chose another operation'.PHP_EOL;
}

public function turnOn()
{
echo 'light on!'.PHP_EOL;
$this->context->setState($this->context->getOnState());
}

public function turnBroken()
{
echo 'light is broke now'.PHP_EOL;
$this->context->setState($this->context->getBrokeState());
}
}

/**
* 灯的开启状态
*/
class onState implements IState
{
private $context;

public function __construct(Light $light)
{
$this->context = $light;
}

public function turnOff()
{
echo 'light off!'.PHP_EOL;
$this->context->setState($this->context->getOffState());
}

public function turnOn()
{
echo 'light is already **on**, please chose another operation'.PHP_EOL;
}

public function turnBroken()
{
echo 'light broken now'.PHP_EOL;
$this->context->setState($this->context->getBrokeState());
}
}

/**
* 新增一个损坏状态
*
* Class brokenState
*/
class brokenState implements IState
{
public function turnOn()
{
echo 'light is broken, can not open now'.PHP_EOL;
}

public function turnOff()
{
echo 'light is already off, because it is broken.'.PHP_EOL;
}

public function turnBroken()
{
echo 'light is already broken.'.PHP_EOL;
}
}

/**
* Class Client
*/
class Client
{
private $light;

public function __construct()
{
$this->light = new Light();
$this->light->turnOn();
$this->light->turnOn();
$this->light->turnOff();
$this->light->turnOff();
$this->light->brokeIt();
$this->light->turnOn();
$this->light->turnOff();
}
}

$client = new Client();
1
2
3
4
5
6
7
light on!
light is already **on**, please chose another operation
light off!
light is already **off**, please chose another operation
light is broke now
light is broken, can not open now
light is already off, because it is broken.