3.10. 状态模式
3.10.1. 目的
根据对象的状态封装一种事务的不同行为。 这更简洁的方式可以在对象在运行时更改其行为,而无需求助于大型的判断条件语句。
3.10.2. UML 图

3.10.3. 代码
在 GitHub 上查看代码
OrderContext.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\State;
6
7class OrderContext
8{
9 private State $state;
10
11 public static function create(): OrderContext
12 {
13 $order = new self();
14 $order->state = new StateCreated();
15
16 return $order;
17 }
18
19 public function setState(State $state)
20 {
21 $this->state = $state;
22 }
23
24 public function proceedToNext()
25 {
26 $this->state->proceedToNext($this);
27 }
28
29 public function toString()
30 {
31 return $this->state->toString();
32 }
33}
State.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\State;
6
7interface State
8{
9 public function proceedToNext(OrderContext $context);
10
11 public function toString(): string;
12}
StateCreated.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\State;
6
7class StateCreated implements State
8{
9 public function proceedToNext(OrderContext $context)
10 {
11 $context->setState(new StateShipped());
12 }
13
14 public function toString(): string
15 {
16 return 'created';
17 }
18}
StateShipped.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\State;
6
7class StateShipped implements State
8{
9 public function proceedToNext(OrderContext $context)
10 {
11 $context->setState(new StateDone());
12 }
13
14 public function toString(): string
15 {
16 return 'shipped';
17 }
18}
StateDone.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\State;
6
7class StateDone implements State
8{
9 public function proceedToNext(OrderContext $context)
10 {
11 // there is nothing more to do
12 }
13
14 public function toString(): string
15 {
16 return 'done';
17 }
18}
3.10.4. 测试
Tests/StateTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\State\Tests;
6
7use DesignPatterns\Behavioral\State\OrderContext;
8use PHPUnit\Framework\TestCase;
9
10class StateTest extends TestCase
11{
12 public function testIsCreatedWithStateCreated()
13 {
14 $orderContext = OrderContext::create();
15
16 $this->assertSame('created', $orderContext->toString());
17 }
18
19 public function testCanProceedToStateShipped()
20 {
21 $contextOrder = OrderContext::create();
22 $contextOrder->proceedToNext();
23
24 $this->assertSame('shipped', $contextOrder->toString());
25 }
26
27 public function testCanProceedToStateDone()
28 {
29 $contextOrder = OrderContext::create();
30 $contextOrder->proceedToNext();
31 $contextOrder->proceedToNext();
32
33 $this->assertSame('done', $contextOrder->toString());
34 }
35
36 public function testStateDoneIsTheLastPossibleState()
37 {
38 $contextOrder = OrderContext::create();
39 $contextOrder->proceedToNext();
40 $contextOrder->proceedToNext();
41 $contextOrder->proceedToNext();
42
43 $this->assertSame('done', $contextOrder->toString());
44 }
45}