3.10. State

3.10.1. Zweck

Kapselt verschiedene Verhaltensweisen für die selbe Routine basierend auf einem Objekt-State. Das kann ein sauberer Weg für ein Objekt sein, sein Verhalten während der Laufzeit ohne komplexe konditionale Bedingungen ändern zu können.

3.10.2. UML-Diagramm

Alt State UML Diagram

3.10.3. Code

Du findest den Code hierzu auf GitHub

ContextOrder.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Behavioral\State;
 6
 7class ContextOrder
 8{
 9    private StateOrder $state;
10
11    public static function create(): ContextOrder
12    {
13        $order = new self();
14        $order->state = new CreateOrder();
15
16        return $order;
17    }
18
19    public function setState(StateOrder $state): void
20    {
21        $this->state = $state;
22    }
23
24    public function proceedToNext(): void
25    {
26        $this->state->proceedToNext($this);
27    }
28
29    public function toString(): string
30    {
31        return $this->state->toString();
32    }
33}

StateOrder.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Behavioral\State;
 6
 7interface StateOrder
 8{
 9    public function proceedToNext(ContextOrder $context): void;
10
11    public function toString(): string;
12}

CreateOrder.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Behavioral\State;
 6
 7class CreateOrder implements StateOrder
 8{
 9    public function proceedToNext(ContextOrder $context): void
10    {
11        $context->setState(new ShippingOrder());
12    }
13
14    public function toString(): string
15    {
16        return 'created';
17    }
18}

ShippingOrder.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Behavioral\State;
 6
 7class ShippingOrder implements StateOrder
 8{
 9    public function proceedToNext(ContextOrder $context): void
10    {
11        $context->setState(new OrderDone());
12    }
13
14    public function toString(): string
15    {
16        return 'shipped';
17    }
18}

OrderDone.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Behavioral\State;
 6
 7class OrderDone implements StateOrder
 8{
 9    public function proceedToNext(ContextOrder $context): void
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\ContextOrder;
 8use PHPUnit\Framework\TestCase;
 9
10class StateTest extends TestCase
11{
12    public function testIsCreatedWithStateCreated(): void
13    {
14        $orderContext = ContextOrder::create();
15
16        $this->assertSame('created', $orderContext->toString());
17    }
18
19    public function testCanProceedToStateShipped(): void
20    {
21        $contextOrder = ContextOrder::create();
22        $contextOrder->proceedToNext();
23
24        $this->assertSame('shipped', $contextOrder->toString());
25    }
26
27    public function testCanProceedToStateDone(): void
28    {
29        $contextOrder = ContextOrder::create();
30        $contextOrder->proceedToNext();
31        $contextOrder->proceedToNext();
32
33        $this->assertSame('done', $contextOrder->toString());
34    }
35
36    public function testStateDoneIsTheLastPossibleState(): void
37    {
38        $contextOrder = ContextOrder::create();
39        $contextOrder->proceedToNext();
40        $contextOrder->proceedToNext();
41        $contextOrder->proceedToNext();
42
43        $this->assertSame('done', $contextOrder->toString());
44    }
45}