/ Gists / 13. State
On gists

13. State

PHP Patterns

pic.md Raw #

State1.php Raw #

<?php

interface State
{
    public function proceedToNext(OrderContext $context);

    public function toString(): string;
}


class StateCreated implements State
{
    public function proceedToNext(OrderContext $context)
    {
        $context->setState(new StateShipped());
    }

    public function toString(): string
    {
        return 'created';
    }
}


class StateShipped implements State
{
    public function proceedToNext(OrderContext $context)
    {
        $context->setState(new StateDone());
    }

    public function toString(): string
    {
        return 'shipped';
    }
}


class StateDone implements State
{
    public function proceedToNext(OrderContext $context)
    {
        // there is nothing more to do
    }

    public function toString(): string
    {
        return 'done';
    }
}


class OrderContext
{
    private State $state;

    public static function create(): OrderContext
    {
        $order = new self();
        $order->state = new StateCreated();

        return $order;
    }

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

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

    public function toString()
    {
        return $this->state->toString();
    }
}

// USAGE
$contextOrder = OrderContext::create(); // created
$contextOrder->proceedToNext(); // shipped
$contextOrder->proceedToNext(); // done

State2.php Raw #

<?php

abstract class Mood {

    public abstract function insult (Person $context);

    public abstract function hug (Person $context);

    public abstract function getName (Person $context, string $name);
}


class Angry extends Mood {

    public function insult (Person $context) {
        $context->say("You too...");
    }

    public function hug (Person $context) {
        $context->say("Hm...");
        $context->setState(new Neutral());
    }

    public function getName (Person $context, string $name) {
        $context->say("{$name}. What's your problem?");
    }

}


class Happy extends Mood {

    public function insult (Person $context) {
        $context->say("Oh! That wasn't nice");
        $context->setState(new Neutral());
    }

    public function hug (Person $context) {
        $context->say("Oh! That was nice, thanks");
    }

    public function getName (Person $context, string $name) {
        $context->say("Oh! Hello dear friend. My name is {$name}");
    }
}


class Neutral extends Mood {

    public function insult (Person $context) {
        $context->say("What the heck do you want?");
        $context->setState(new Angry());
    }

    public function hug (Person $context) {
        $context->say("Thanks");
        $context->setState(new Happy());
    }

    public function getName (Person $context, string $name) {
        $context->say("My name is {$name}");
    }

}


class Person {

    private $currentMood;
    private $name;

    public function __construct (Mood $mood, string $name) {
        $this->setState($mood);
        $this->name = $name;
    }

    public function setState (Mood $mood) {
        $this->currentMood = $mood;
    }

    public function insult () {
        $this->currentMood->insult($this);
    }

    public function getName () {
        $this->currentMood->getName($this, $this->name);
    }

    public function hug () {
        $this->currentMood->hug($this);
    }

    public function say (string $msg) {
        echo($msg . PHP_EOL);
    }
}


// USAGE
$jan = new Person(new Neutral(), "Jan");
$jan->getName();
$jan->insult();
$jan->getName();
$jan->hug();
$jan->getName();
$jan->hug();
$jan->getName();