盒子
盒子
文章目录
  1. 写在前
  2. 空调开开
  3. 状态
  4. 开关状态
  5. 遥控器
  6. 代码实现
  7. 最佳实践

PHP状态模式之天气热了把空调开开

写在前

夏天不可辜负的东西有三样:西瓜、海滩和冰淇淋。然而,单靠这三样还不足以度过炎炎夏日啊~

空调开开

夏天到了,对于南方的同学来说,回到家第一件事就是找空调遥控器,这个遥控器是个好东西,按一下开关就可以让我们清凉一夏~

那么,我们会想,遥控器是怎么保存开关的状态的呢?为什么我们按一下按钮就开,按一下就关,同一个按钮,两种状态,有点神奇~

状态

无论是开,还是关。它们都是一种状态,所以,我们有一个状态接口,这个状态是遥控器控制的,所以它有一个handle方法。

1
2
3
4
interface IState
{
public function handle(RemoteController $controller);
}

开关状态

开、关状态都实现了状态接口,所以它们都要实现handle方法,这是具体的状态。

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
/**
* 开机状态
* Class OnState
*/
class OnState implements IState
{
public function handle(RemoteController $controller)
{
echo '开空调';
$controller->setState(new self);
}
}


/**
* 关机状态
* Class OffState
*/
class OffState implements IState
{
public function handle(RemoteController $controller)
{
echo '关空调';
$controller->setState(new self);
}
}

遥控器

我们还需要一个遥控器来保存这些状态,当然,这个遥控器有一个按钮给我们点击

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 遥控器
* Class RemoteController
*/
class RemoteController
{
private $_state = null;

public function __construct(IState $state)
{
$this->_state = $state;
}

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

public function onClick()
{
$this->_state->handle($this);
}
}

代码实现

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
define("NEWLINE",chr(10));

interface IState
{
public function handle(RemoteController $controller);
}

/**
* 开机状态
* Class OnState
*/
class OnState implements IState
{
public function handle(RemoteController $controller)
{
echo '开空调' . NEWLINE;
$controller->setState(new self);
}
}


/**
* 关机状态
* Class OffState
*/
class OffState implements IState
{
public function handle(RemoteController $controller)
{
echo '关空调' . NEWLINE;
$controller->setState(new self);
}
}


/**
* 遥控器
* Class RemoteController
*/
class RemoteController
{
private $_state = null;

public function __construct(IState $state)
{
$this->_state = $state;
}

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

public function onClick()
{
$this->_state->handle($this);
}
}

// 默认开空调
$controller = new RemoteController(new OnState());
$controller->onClick();
$controller->onClick();
$controller->onClick();
$controller->onClick();

// 开空调
// 关空调
// 开空调
// 关空调

最佳实践

上面,我们实现了一个遥控器来控制开关状态,但是细心的你会发现,每次点击按钮,我们都要重新做一个状态(new OnState() 或者 new OffState())出来,这不太好。无论是开还是关状态,都应该在开机的时候就存在的,不需要我们重复去做。所以,我们使用单例模式,让开、关状态都只定义一次。

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
define("NEWLINE",chr(10));

interface IState
{
public function handle(RemoteController $controller);
}

/**
* 开机状态
* Class OnState
*/
class OnState implements IState
{
private static $_instance = null;

private function __construct() {}

public function getInstance()
{
if (is_null(self::$_instance)) {
self::$_instance = new self;
}

return self::$_instance;
}

public function handle(RemoteController $controller)
{
echo '开空调' . NEWLINE;
$controller->setState(OffState::getInstance());
}
}


/**
* 关机状态
* Class OffState
*/
class OffState implements IState
{
private static $_instance = null;

private function __construct() {}

public function getInstance()
{
if (is_null(self::$_instance)) {
self::$_instance = new self;
}

return self::$_instance;
}

public function handle(RemoteController $controller)
{
echo '关空调' . NEWLINE;
$controller->setState(OnState::getInstance());
}
}


/**
* 遥控器
* Class RemoteController
*/
class RemoteController
{
private $_state = null;

public function __construct(IState $state)
{
$this->_state = $state;
}

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

public function onClick()
{
$this->_state->handle($this);
}
}

// 默认开空调
$controller = new RemoteController(OnState::getInstance());
$controller->onClick();
$controller->onClick();
$controller->onClick();
$controller->onClick();

// 开空调
// 关空调
// 开空调
// 关空调

done~

请我喝一杯咖啡
扫一扫,支持funsoul
  • 微信扫一扫