您好,登錄后才能下訂單哦!
這篇文章主要介紹了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()對象來實現開關狀態的切換。
看出門道了嘛?這里把狀態的變化給封裝到外部的實現類去了,并不是這個上下文或者目標類內部來進行狀態的切換了
那么狀態模式的意義呢?這個默認類圖的例子過于簡單,其實狀態模式的真正目的是為了解決復雜的if嵌套問題的,把復雜的if嵌套條件放到一個個的外部狀態類中去判斷,在后面的實例中我們會看到
適用于:一個對象的行為取決于它的狀態,并且它的必須在運行時刻根據狀態改變自己的行為;一個操作中含有大量的多分支條件語句,且這些分支依賴于該對象的狀態;
狀態模式的特點是:它將與特定狀態相關的行為局部化;它使得狀態轉換顯式化;State對象可以被共享;
常見于訂單系統、會員系統、OA系統中,也就是流程中會出現各種狀態變化的情況,都可以使用狀態模式來進行整體的設計與架構
我們的手機系統內定制了自己的商城系統,可以在手機上方便的下單購買我們的商品。一個訂單(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;
說明
如果不使用狀態模式,在Member的discount()方法中,我們可能需要寫很多層if...else...判斷條件
同時,這也帶來了方法體會越來越長,越來越難以維護的問題
狀態模式正是為了解決這個問題而存在的
當discount()行為的結果依賴于Member對象本身的狀態(會員分)時,狀態模式就是最佳的選擇了,也就是上面所說的一個對象的行為取決于它的狀態
感謝你能夠認真閱讀完這篇文章,希望小編分享的“PHP中狀態模式指的是什么”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。