PHP設計模式——狀態模式

前言

狀態設計模式是Gof提出的最吸引人的模式之一,也是一種最有用的模式。遊戲一般就採用狀態模式,由於遊戲中的對象每每會很是頻繁地改變狀態。狀態模式的做用就是容許對象在狀態改變時改變其行爲。還有不少其餘模擬應用(不必定是遊戲)也依賴於狀態模式。本文將會談到並舉例說明。
按照傳統思惟,若是有多個狀態的話通常就是用if、else if、switch處理了,可是這類的代碼看起來極其不美觀,最重要的是沒什麼拓展性,維護性,複用性,還會出現「牽一髮而動全身」的狀況。若是把這些狀態封裝起來,就能夠減小大量的判斷,那麼就要用狀態模式了。php

效果圖

圖片描述

需求分析

一、代碼遵循可拓展性強,可維護性強,複用性強,杜絕」牽一髮而動全身」的狀況。
二、減小使用大量的if、else if、switch判斷。設計模式

核心代碼

一、Work.php(它定義了時間程序須要的接口並維護一個具體狀態角色的實例,將與狀態相關的操做委託給當前的具體對象來處理。)yii

<?php 
namespace common\status;

//工做狀態  
class Work  
{  
    private $current;  
    public $hour;

    public function __construct()  
    {  
        $this->current = new EarlyMorning();  
    }
    //設置狀態  
    public function SetState($s)  
    {
        $this->current = $s;  
    }  
  
    public function WriteCode()  
    { 
       return $this->current->WriteCode($this);  
    }  
}

二、IState.php(定義一個接口以封裝使用上下文環境的的一個特定狀態相關的行爲。)this

<?php
namespace common\status;

//狀態接口  
interface IState  
{  
    public function WriteCode($w);  
}

三、EarlyMorning.php(實現抽象狀態定義的接口。)spa

//早晨工做狀態  
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();  //注意:這裏必須都要return返回,不然調用客戶端代碼的時候沒法賦值給$call。
        }   
           
    }  
} 

//早上工做狀態  
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();  
        }    
    }  
} 

//上午工做狀態  
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();  
        }    
    }  
} 

//中午工做狀態  
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();  
        }    
    }  
} 

//下午工做狀態  
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();  
        }    
    }  
}

//傍晚工做狀態  
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();  
        }   
    }  
} 

//晚上工做狀態  
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();  
        }   
    }  
} 

//夜裏工做狀態  
class GoodAtNight implements IState  
{ 
    public function WriteCode($w)  
    {  
        return Yii::t('yii','Good at night');  
    }  
}

調用客戶端代碼

<?php

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

增長狀態

一、例如:在原來的應用中增長個「半夜的狀態」。
1.一、在原夜裏工做狀態類增長個if判斷,符合條件時調用半夜的工做狀態。.net

<?php  
namespace common\status;

use Yii;
use common\status\IState;

//夜裏工做狀態  
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.二、新增一個半夜工做狀態類,裏面寫要執行的行爲。設計

<?php  
namespace common\status;

use Yii;
use common\status\IState;

//半夜工做狀態  
class Midnight implements IState  
{ 
    public function WriteCode($w)  
    { 
        return Yii::t('yii','midnight');   
    }  
}

怎麼樣,增長一個狀態是否是很簡單?拓展性很是好。code

提醒注意

一、實現狀態接口類中的$w->WriteCode()必需要return返回,不然調用客戶端代碼的時候沒法賦值給$call,會直接echo輸出。
二、實現狀態接口類中的public function WriteCode($w)方法裏的$w對象類應該是Work對象,不能是當前類的對象。對象

總結分析

一、優勢
1.一、狀態模式將與特定狀態相關的行爲局部化,而且將不一樣狀態的行爲分割開來。
1.二、全部狀態相關的代碼都存在於某個ConcereteState中,因此經過定義新的子類很容易地增長新的狀態和轉換。
1.三、狀態模式經過把各類狀態轉移邏輯分不到State的子類之間,來減小相互間的依賴。
二、缺點
2.一、致使較多的ConcreteState子類。blog

相關資料

狀態模式

相關文章
相關標籤/搜索