溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

PHP中狀態(tài)模式指的是什么

發(fā)布時間:2021-07-28 09:51:56 來源:億速云 閱讀:124 作者:小新 欄目:編程語言

這篇文章主要介紹了PHP中狀態(tài)模式指的是什么,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

狀態(tài)模式從字面上其實并不是很好理解。這里的狀態(tài)是什么意思呢?保存狀態(tài)?那不就是備忘錄模式了。其實,這里的狀態(tài)是類的狀態(tài),通過改變類的某個狀態(tài),讓這個類感覺像是換了一個類一樣。說起來有點拗口吧,先學(xué)習(xí)概念之后再看。

Gof類圖及解釋

GoF定義:允許一個對象在其內(nèi)部狀態(tài)改變時改變它的行為。對象看起來似乎修改了它的類

GoF類圖

PHP中狀態(tài)模式指的是什么

代碼實現(xiàn)

class Context
{
    private $state;
    public function SetState(State $state): void
    {
        $this->state = $state;
    }
    public function Request(): void
    {
        $this->state = $this->state->Handle();
    }
}

一個上下文類,也可以看作是目標(biāo)類,它的內(nèi)部有一個狀態(tài)對象。當(dāng)調(diào)用Request()的時候,去調(diào)用狀態(tài)類的Handle()方法。目的是當(dāng)前上下文類狀態(tài)的變化都由外部的這個狀態(tài)類來進行操縱。

interface State
{
    public function Handle(): State;
}

class ConcreteStateA implements State
{
    public function Handle(): State
    {
        echo '當(dāng)前是A狀態(tài)', PHP_EOL;
        return new ConcreteStateB();
    }
}

class ConcreteStateB implements State
{
    public function Handle(): State
    {
        echo '當(dāng)前是B狀態(tài)', PHP_EOL;
        return new ConcreteStateA();
    }
}

抽象狀態(tài)接口及兩個具體實現(xiàn)。這兩個具體實現(xiàn)實際上是在相互調(diào)用。實現(xiàn)的效果就是上下文類每調(diào)用一次Request()方法,內(nèi)部的狀態(tài)類就變成別一個狀態(tài)。就像一個開關(guān),在打開與關(guān)閉中來回切換一樣。

$c = new Context();
$stateA = new ConcreteStateA();
$c->SetState($stateA);
$c->Request();
$c->Request();
$c->Request();
$c->Request();

客戶端的實現(xiàn),實例化上下文對象并設(shè)置初始的狀態(tài),然后通過不停的調(diào)用Request()對象來實現(xiàn)開關(guān)狀態(tài)的切換。

  • 看出門道了嘛?這里把狀態(tài)的變化給封裝到外部的實現(xiàn)類去了,并不是這個上下文或者目標(biāo)類內(nèi)部來進行狀態(tài)的切換了

  • 那么狀態(tài)模式的意義呢?這個默認類圖的例子過于簡單,其實狀態(tài)模式的真正目的是為了解決復(fù)雜的if嵌套問題的,把復(fù)雜的if嵌套條件放到一個個的外部狀態(tài)類中去判斷,在后面的實例中我們會看到

  • 適用于:一個對象的行為取決于它的狀態(tài),并且它的必須在運行時刻根據(jù)狀態(tài)改變自己的行為;一個操作中含有大量的多分支條件語句,且這些分支依賴于該對象的狀態(tài);

  • 狀態(tài)模式的特點是:它將與特定狀態(tài)相關(guān)的行為局部化;它使得狀態(tài)轉(zhuǎn)換顯式化;State對象可以被共享;

  • 常見于訂單系統(tǒng)、會員系統(tǒng)、OA系統(tǒng)中,也就是流程中會出現(xiàn)各種狀態(tài)變化的情況,都可以使用狀態(tài)模式來進行整體的設(shè)計與架構(gòu)

我們的手機系統(tǒng)內(nèi)定制了自己的商城系統(tǒng),可以在手機上方便的下單購買我們的商品。一個訂單(Context)會有多種狀態(tài)(State),比如未支付、已支付、訂單完成、訂單退款等等一大堆狀態(tài)。我們把這些狀態(tài)都放在了對應(yīng)的狀態(tài)類里去實現(xiàn),不同的狀態(tài)類都會再去調(diào)用該狀態(tài)下一步的動作,比如已支付后就等待收貨、退款后就等待買家填寫物流單號等,這樣,狀態(tài)模式就在我們的商城中被靈活的運用起來咯!!

完整代碼:https://github.com/zhangyue0503/designpatterns-php/blob/master/22.state/source/state.php

實例

通常的商城應(yīng)用中都會有會員體系的存在,一般等級越高的會員可以享受的折扣也會越多,這個時候,運用狀態(tài)模式就能很輕松的獲得會員的等級折扣。當(dāng)然,最主要的是,使用狀態(tài)模式可以在需要添加或者刪除會員等級時只添加對應(yīng)的會員折扣狀態(tài)子類就可以了。其他業(yè)務(wù)代碼都不需要變動,我們一起來看看具體實現(xiàn)吧!

會員折扣圖

PHP中狀態(tài)模式指的是什么

完整源碼:https://github.com/zhangyue0503/designpatterns-php/blob/master/22.state/source/state-member.php

<?php

class Member
{
    private $state;
    private $score;

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

    public function SetScore($score)
    {
        $this->score = $score;
    }

    public function GetScore()
    {
        return $this->score;
    }

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

interface State
{
    public function discount($member);
}

class PlatinumMemeberState implements State
{
    public function discount($member)
    {
        if ($member->GetScore() >= 1000) {
            return 0.80;
        } else {
            $member->SetState(new GoldMemberState());
            return $member->discount();
        }
    }
}

class GoldMemberState implements State
{
    public function discount($member)
    {
        if ($member->GetScore() >= 800) {
            return 0.85;
        } else {
            $member->SetState(new SilverMemberState());
            return $member->discount();
        }
    }
}

class SilverMemberState implements State
{
    public function discount($member)
    {
        if ($member->GetScore() >= 500) {
            return 0.90;
        } else {
            $member->SetState(new GeneralMemberState());
            return $member->discount();
        }
    }
}

class GeneralMemberState implements State
{
    public function discount($member)
    {
        return 0.95;
    }
}

$m = new Member();
$m->SetState(new PlatinumMemeberState());

$m->SetScore(1200);
echo '當(dāng)前會員' . $m->GetScore() . '積分,折扣為:' . $m->discount(), PHP_EOL;

$m->SetScore(990);
echo '當(dāng)前會員' . $m->GetScore() . '積分,折扣為:' . $m->discount(), PHP_EOL;

$m->SetScore(660);
echo '當(dāng)前會員' . $m->GetScore() . '積分,折扣為:' . $m->discount(), PHP_EOL;

$m->SetScore(10);
echo '當(dāng)前會員' . $m->GetScore() . '積分,折扣為:' . $m->discount(), PHP_EOL;

說明

  • 如果不使用狀態(tài)模式,在Member的discount()方法中,我們可能需要寫很多層if...else...判斷條件

  • 同時,這也帶來了方法體會越來越長,越來越難以維護的問題

  • 狀態(tài)模式正是為了解決這個問題而存在的

  • 當(dāng)discount()行為的結(jié)果依賴于Member對象本身的狀態(tài)(會員分)時,狀態(tài)模式就是最佳的選擇了,也就是上面所說的一個對象的行為取決于它的狀態(tài)

感謝你能夠認真閱讀完這篇文章,希望小編分享的“PHP中狀態(tài)模式指的是什么”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

php
AI