3.10. State

3.10.1. Rôle

Encapsule des comportements différents pour la même routine en fonction de l’état de l’objet. Cela peut être un moyen plus propre pour un objet de changer son comportement au moment de l’exécution sans avoir recours à de grandes déclarations conditionnelles monolithiques.

3.10.2. Diagramme UML

Alt State UML Diagram

3.10.3. Code

Vous pouvez également trouver ce code sur 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. Test

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}