PHP design pattern – state mode

Time:2022-6-11

preface

State design pattern is one of the most attractive patterns proposed by GOF, and it is also one of the most useful patterns. Games usually use state mode, because the objects in the game often change state very frequently. The purpose of a state pattern is to allow an object to change its behavior when its state changes. Many other simulation applications (not necessarily games) also rely on state mode. This article will talk about and illustrate.
According to the traditional thinking, if there are multiple states, it is usually handled with if, else if and switch. However, this kind of code looks extremely unsightly. The most important thing is that it has no expansibility, maintainability and reusability. There will also be a situation of “pulling the trigger and affecting the whole body”. If you can reduce a lot of judgment by encapsulating these States, you need to use the state pattern.

design sketch

requirement analysis

1. The code is highly expandable, maintainable and reusable, and the situation that “one hair touches the whole body” is eliminated.
2. Reduce the use of a large number of if, else if, and switch judgments.

Core code

1、Work. PHP (it defines the interface required by the time program, maintains an instance of a specific state role, and delegates the state related operations to the current concrete object for processing.)

<?php 
namespace common\status;

//Working status  
class Work  
{  
    private $current;  
    public $hour;

    public function __construct()  
    {  
        $this->current = new EarlyMorning();  
    }
    //Set status  
    public function SetState($s)  
    {
        $this->current = $s;  
    }  
  
    public function WriteCode()  
    { 
       return $this->current->WriteCode($this);  
    }  
}

2、IState. PHP (define an interface to encapsulate a specific state related behavior that uses the context.)

<?php
namespace common\status;

//Status interface  
interface IState  
{  
    public function WriteCode($w);  
}

3、EarlyMorning. PHP (an interface that implements abstract state definitions.)

//Morning working status  
class EarlyMorning implements IState  
{ 
    public function WriteCode($w)  
    {  
        if($w->hour<6)  
        {  
           return Yii::t('yii','Good Early morning'); 
        }else{  
            $w->SetState(new GoodMorning());  
           return $w->WriteCode();  // Note: return must be returned here, otherwise $call cannot be assigned when calling the client code.
        }   
           
    }  
} 

//Morning working status  
class GoodMorning implements IState  
{ 
    public function WriteCode($w)  
    {  
        if($w->hour<9)  
        {  
           return Yii::t('yii','Good morning'); 
        }else{  
            $w->SetState(new GoodForenoon());  
           return $w->WriteCode();  
        }    
    }  
} 

//Morning working status  
class GoodForenoon implements IState  
{ 
    public function WriteCode($w)  
    {   
        if($w->hour<12)  
        { 
           return Yii::t('yii','Good forenoon'); 
        }else{  
            $w->SetState(new GoodNoon());  
           return $w->WriteCode();  
        }    
    }  
} 

//Working status at noon  
class GoodNoon implements IState  
{ 
    public function WriteCode($w)  
    { 
        if($w->hour<14)  
        {  
           return Yii::t('yii','Good noon'); 
        }else{  
            $w->SetState(new GoodAfternoon());  
           return $w->WriteCode();  
        }    
    }  
} 

//Afternoon working status  
class GoodAfternoon implements IState  
{ 
    public function WriteCode($w)  
    {  
        if($w->hour<17)  
        {  
           return Yii::t('yii','Good afternoon'); 
        }else{  
            $w->SetState(new GoodDusk());  
           return $w->WriteCode();  
        }    
    }  
}

//Working state in the evening  
class GoodDusk implements IState  
{ 
    public function WriteCode($w)  
    { 
        if($w->hour<19)  
        {  
           return Yii::t('yii','Good dusk'); 
        }else{  
            $w->SetState(new GoodNight());  
           return $w->WriteCode();  
        }   
    }  
} 

//Working status at night  
class GoodNight implements IState  
{ 
    public function WriteCode($w)  
    {  
        if($w->hour<22)  
        {  
           return Yii::t('yii','Good night'); 
        }else{  
            $w->SetState(new GoodAtNight());  
           return $w->WriteCode();  
        }   
    }  
} 

//Night working status  
class GoodAtNight implements IState  
{ 
    public function WriteCode($w)  
    {  
        return Yii::t('yii','Good at night');  
    }  
}

Call client code

<?php

use common\status\Work;
//Greetings
$emergWork = new Work();  
$emergWork->hour = date("H");  
$call=$emergWork->WriteCode();

Add status

1. For example, add “midnight status” to the original application.
1.1. Add an if judgment to the original night working state class, and call the midnight working state when the conditions are met.

<?php  
namespace common\status;

use Yii;
use common\status\IState;

//Night working status  
class GoodAtNight implements IState  
{ 
    public function WriteCode($w)  
    {  
        if($w->hour<23)  
        {   
            return Yii::t('yii','Good at night');  
        }else{  
            $w->SetState(new Midnight());  
            return  $w->WriteCode();  
        }   
    }  
}

1.2. Add a midnight work status class to write the behaviors to be executed.

<?php  
namespace common\status;

use Yii;
use common\status\IState;

//Midnight working state  
class Midnight implements IState  
{ 
    public function WriteCode($w)  
    { 
        return Yii::t('yii','midnight');   
    }  
}

How about adding a status? Extremely expandable.

Reminder

1. The $w->writecode() in the implementation status interface class must be returned. Otherwise, when calling the client code, it cannot be assigned to $call and will be output directly by echo.
2. The $w object class in the public function writecode ($w) method in the implementation status interface class should be a work object, not an object of the current class.

Summary analysis

1. Advantages
1.1. State mode localizes the behavior related to a specific state and separates the behavior of different states.
1.2 all state related codes exist in a conceretestate, so it is easy to add new states and transitions by defining new subclasses.
1.3. State mode reduces mutual dependence by dividing various state transition logics into subclasses of state.
2. Disadvantages
2.1. More concretestate subclasses.

Relevant information

Status mode