在之前的文章《一起聊聊PHP中的單例模式》中我們介紹了PHP中的單例模式,以下這篇文章帶大家了解一下PHP設計模式中的狀態模式
狀態模式從字面上其實不是很好理解。這裡的狀態是什麼意思呢?保存狀態?那不就是備忘錄模式了。其實,這裡的狀態是類別的狀態,透過改變類別的某個狀態,讓這個類別感覺像是換了一個類別一樣。說起來有點拗口吧,先學習概念之後再看。
GoF定義:允許一個物件在其內部狀態改變時改變它的行為。物件看起來似乎修改了它的類別
GoF類別圖
#程式碼實現
class Context { private $state; public function SetState(State $state): void { $this->state = $state; } public function Request(): void { $this->state = $this->state->Handle(); } }
一個上下文類,也可以看作是目標類,它的內部有一個狀態物件。當呼叫Request()的時候,去呼叫狀態類別的Handle()方法。目的是當前上下文類別狀態的變化都由外部的這個狀態類別來進行操縱。
interface State { public function Handle(): State; } class ConcreteStateA implements State { public function Handle(): State { echo '当前是A状态', PHP_EOL; return new ConcreteStateB(); } } class ConcreteStateB implements State { public function Handle(): State { echo '当前是B状态', PHP_EOL; return new ConcreteStateA(); } }
抽象狀態介面及兩個具體實作。這兩個具體實作其實是在相互呼叫。實現的效果就是上下文類別每呼叫一次Request()方法,內部的狀態類別就變成別一個狀態。就像一個開關,在開啟與關閉中來回切換一樣。
$c = new Context(); $stateA = new ConcreteStateA(); $c->SetState($stateA); $c->Request(); $c->Request(); $c->Request(); $c->Request();
客戶端的實現,實例化上下文物件並設定初始的狀態,然後透過不停的呼叫Request()物件來實現開關狀態的切換。
#我們的手機系統內客製了自己的商城系統,可以在手機上方便的下單購買我們的商品。一個訂單(Context)會有多種狀態(State),例如未支付、已支付、訂單完成、訂單退款等等一大堆狀態。我們把這些狀態都放在了對應的狀態類別裡去實現,不同的狀態類別都會再去調用該狀態下一步的動作,例如已支付後就等待收貨、退款後就等待買家填寫物流單號等,這樣,狀態模式就在我們的商城中被靈活的運用起來咯! !
完整程式碼:https://github.com/zhangyue0503/designpatterns-php/blob/master/22.state/source/state.php
通常的商城應用程式中都會有會員體系的存在,一般等級越高的會員可以享受的折扣也會越多,這個時候,運用狀態模式就能很輕鬆的獲得會員的等級折扣。當然,最主要的是,使用狀態模式可以在需要新增或刪除會員等級時只新增對應的會員折扣狀態子類別就可以了。其他業務程式碼都不需要變動,我們一起來看看具體實作吧!
會員折扣圖
#完整原始碼: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 '当前会员' . $m->GetScore() . '积分,折扣为:' . $m->discount(), PHP_EOL; $m->SetScore(990); echo '当前会员' . $m->GetScore() . '积分,折扣为:' . $m->discount(), PHP_EOL; $m->SetScore(660); echo '当前会员' . $m->GetScore() . '积分,折扣为:' . $m->discount(), PHP_EOL; $m->SetScore(10); echo '当前会员' . $m->GetScore() . '积分,折扣为:' . $m->discount(), PHP_EOL;
#說明
原文網址:https://juejin.cn/post/6844903991562731534
作者:硬核專案經理
推薦學習:《PHP影片教學》
以上是PHP中什麼是狀態模式?透過實例來了解它的詳細內容。更多資訊請關注PHP中文網其他相關文章!