-
Notifications
You must be signed in to change notification settings - Fork 50
/
Copy pathState.php
154 lines (128 loc) · 2.8 KB
/
State.php
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
<?php
/*
状态模式:允许对象在内部状态改变时,改变它的行为。
在示例代码中,我们使用一个简单的售卖机模型进行实现:
等待投币:状态1
->投币:动作1
投币完成:状态2
->扳动把手:动作2
结束交易:状态3
->获取产品:动作3
...返回等待投币状态...
*/
/*
抽象状态类
*/
abstract class State
{
public $machine;
public function __construct($machine)
{
$this->machine = $machine;
}
//投币动作
public function putCoin()
{
throw new Exception('you can not put coin!');
}
//扳动把手动作
public function turnHandle()
{
throw new Exception('you can not turn handle!');
}
//获取产品动作
public function getProduct()
{
throw new Exception('you can not get product!');
}
}
class WaitCoinState extends State
{
public function putCoin()
{
$this->machine->setCurStateObject(Machine::STATE_COMPLETE_COIN);
var_export("put coin!");
}
}
class CompleteCoinState extends State
{
public function turnHandle()
{
$this->machine->setCurStateObject(Machine::STATE_END_TRANSACTION);
var_export('turn handle!');
}
}
class EndTransactionState extends State
{
public function getProduct()
{
$this->machine->setCurStateObject(Machine::STATE_WAIT_COIN);
var_export('get product!');
}
}
class Machine
{
const STATE_WAIT_COIN = 1;
const STATE_COMPLETE_COIN = 2;
const STATE_END_TRANSACTION = 3;
private $curStateObject;
private $statePool = [
self::STATE_WAIT_COIN => 'WaitCoinState',
self::STATE_COMPLETE_COIN => 'CompleteCoinState',
self::STATE_END_TRANSACTION => 'EndTransactionState',
];
//初始化状态
public function __construct()
{
$this->setCurStateObject(self::STATE_WAIT_COIN);
}
private function generalStateObject($state)
{
$className = $this->statePool[$state] ?? null;
if (is_null($className)) {
throw new Exception("state is not exists!");
}
return new $className($this);
}
public function setCurStateObject($state)
{
$this->curStateObject = $this->generalStateObject($state);
}
public function getCurStateObject()
{
return $this->curStateObject;
}
//把行为委托给特定的状态类执行
public function __call($name, $arguments)
{
if (method_exists($this->curStateObject, $name)) {
return call_user_func_array([$this->curStateObject, $name], $arguments);
} else {
throw new Exception('method ('.$name.') is not exists!');
}
}
}
class Test
{
public function run()
{
try {
$machine = new Machine();
$machine->putCoin();
echo '<br>';
$machine->turnHandle();
echo '<br>';
$machine->getProduct();
echo '<br>';
$machine->putCoin();
echo '<br>';
$machine->turnHandle();
echo '<br>';
$machine->getProduct();
} catch (Exception $e) {
var_export($e->getMessage());
}
}
}
$test = new Test();
$test->run();