PHP Design Patterns - State Patterns

Keywords: ASP.NET PHP

Preface

The state design pattern is one of the most attractive patterns proposed by Gof, and it is also one of the most useful patterns. The game usually uses state mode, because the object in the game often changes state very frequently. The function of state mode is to allow an object to change its behavior when the state changes. Many other simulation applications (not necessarily games) also depend on state mode. This article will talk about and illustrate with examples.
According to traditional thinking, if there are more than one state, it is usually handled with if, else if, switch, but this kind of code looks extremely ugly, the most important thing is that there is no extensibility, maintainability, reusability, and there will be "pull one trigger and move the whole body" situation. If you encapsulate these states, you can reduce a lot of judgments, so you need to use the state mode.

Design sketch

requirement analysis

1. Code compliance has strong extensibility, maintainability and reusability. It can eliminate the situation of "pulling the trigger and moving the whole body".
2. Reduce the use of a large number of if, else if, switch judgments.

Core code

1. Work.php (which defines the interface needed by the time program and maintains an instance of a specific state role, delegating state-related operations to the current specific object.)

<?php 
namespace common\status;

//working condition  
class Work  
{  
    private $current;  
    public $hour;

    public function __construct()  
    {  
        $this->current = new EarlyMorning();  
    }
    //Setup state  
    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 using context.)

<?php
namespace common\status;

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

3. EarlyMorning.php.

  
//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: You must return here, otherwise you cannot assign $call when calling 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 state 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();  
        }    
    }  
} 

//Working state in the afternoon  
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 state 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();  
        }   
    }  
} 

//Working state at night  
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(); 

Increase state

1. For example, add a "midnight state" to the original application.
1.1. Add an if judgment to the original night working state class, and call the midnight working state when it meets the requirements.

<?php  
namespace common\status;

use Yii;
use common\status\IState;

//Working state at night  
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 new midnight working state class, which writes the behavior to be performed.

<?php  
namespace common\status;

use Yii;
use common\status\IState;

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

Well, is it easy to add a state? Extension is very good.

Caution

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

Summary and analysis

1, advantages
1.1. The state pattern localizes the behavior related to a particular state and separates the behavior of different states.
1.2. All state-related code exists in a ConcereteState, so it is easy to add new states and transitions by defining new subclasses.
1.3. The State mode reduces the interdependence by dividing all kinds of State transition logic into subclasses of State.
2, shortcomings
2.1. Causes more ConcreteState subclasses.

Related information

State mode

Posted by optikalefx on Sun, 07 Apr 2019 11:18:29 -0700