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.