最初为了减少代码中的逻辑判断,使用了该模式,不过大家在实际中还是需要权衡,太多的类未必就比if{…}else{…}更好。

在这儿给大家说点事儿。我的博客搬家到github主页上了。我的博客。以后首发都在github上了。csdn也会继续更新。可能就是稍微慢一下。

另外最近搞了一个支付的开源项目。这是项目地址 目前已经支持:

  • 支付宝的 即时到帐、移动支付、加密退款接口。
  • 微信的目前已经支持:app支付、扫码支付、H5支付

项目还存在些bug,正在不断结合公司业务进行修改。后期可能会支持的越来越全面。

状态模式

废话不多说了,回到本文主题: 状态模式

允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

说实话,这定义真JB不是怎么读的懂。不过咱要试着去理解其中的精髓。谁让咱们有颗向上的心呢?

一句句来。

先说这一句: 允许一个对象在其内部状态改变时改变它的行为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

class Context {
private $state;

public function __construct($state)
{

$this->state = $state;
}

public function change()
{

if ($this->state == 1) {
echo '我是好人';
} elseif ($this->state == 2) {
echo '我要当坏人';
} elseif (...) {
// 其他状态
}
else {
echo '爱好和平!';
}
}
}

以下我要开始自己的理解了,这个理解不一定是上面定义的本意,但是绝对讲人话,有帮助,可实战。

如果 state 传入的值不同,则会得到不同的行为。那么这就是我理解的这一句话的意思。再说白话一点,根据不同的条件,执行不同的逻辑。

对象看起来似乎修改了它的类 这一句更扯淡,真不知道这些人怎么想的,就不能说的通俗些?我觉得嘛,这个概念能懂就懂,不懂呢,你就这么办:那就是对于每一个条件中的逻辑,移入到不同的类中,这些类要实现一个统一的接口。还不懂?上代码

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

interface State()
{
// 注意这里的Context 我在后面会讲到。不等同于上面的 Context 类哦
public function handle(Context $context);
}

// 状态A
class StateA implements State
{
public function handle(Context $context)
{
if ($context->term = 1) {
// 处理逻辑,并终止程序
} else {
$context.setState(new StateB());
}
}
}

// 状态B
class StateB implements State
{
public function handle(Context $context)
{
if ($context->term = 2) {
// 处理逻辑,并终止程序
} else {
$context.setState(new StateC());
}
}
}

// 状态C
class StateC implements State
{
public function handle(Context $context)
{
// 如果还有其他状态,则继续往下走。如果没有,就在次终止程序
}
}


// 新的Context类的实现
class Context
{
private $state;// 用来保存 State 对象

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

public function request()
{
$this->state->handle($this);
}
}

上面的代码基本上就已经演示了 状态模式 。有看官急了,写的什么狗屎?怎么用,哪儿可以用?别急,等我把这个逼装完。

模式类图

继续装逼,上类图。

类图

从这个图中可以看出,纯种的状态模式,包括了以下三个角色:

  • Context: 环境类。它呢需要在代码中传给具体的 State 类,这样State类才能改变它。记得这句 对象看起来似乎修改了它的类 吗?就着这句话再去理解下这个类。他保存有当前的状态。
  • State: 抽象的状态接口 。让具体的状态都要实现这个接口,Context依赖接口进行编程。
  • ConcreteState: 具体的状态类。专门用于处理某一个状态,如果处理不了就转发出去。

使用场景

上面讲那么多,不能真刀真枪的用到项目中,都是耍流氓。在我们的项目中其实有特别多的地方可以用到状态模式。

  • 如果项目中存在太多的 if {...} elseif {...} else {...} 。那么你应该考虑状态模式。我觉得这个是重点考虑对象
  • 如果每个状态中处理的业务逻辑特别复杂·那么建议考虑这种方式。
  • 最后一点,如果代码中的状态相对固定。比如一个电商中购买商品的流程:未支付、已过期、待发货(已支付)、已发货、已收货。那么这种状态基本上定下来不会有太大变化,状态发生在内部中,顺序固定,不需要客户端进行处理。

以上三种情况是我建议的方式。如果大家还有总结的经验,欢迎分享。

这里有个问题,待我写完 职责链模式 之后再来分享。因为这二者有相当多的共同之处。大家一定认真阅读我写的 使用场景 的最后一点。