秒懂设计模式之状态模式(State Pattern)
[版權申明] 非商業目的注明出處可自由轉載
博文地址:https://blog.csdn.net/ShuSheng0007/article/details/116375477
出自:shusheng007
設計模式匯總篇,一定要收藏:
永不磨滅的設計模式(有這一篇真夠了,拒絕標題黨)
文章目錄
- 概述
- 類型
- 難度
- 定義
- 使用場景
- UML類圖
- 實例
- 第一,定義一個狀態接口
- 第二,定義一個物流Context類
- 第三,實現各種狀態類
- 第四, 客戶端使用
- 技術要點總結
- 優缺點
- 優點
- 缺點
- 狀態模式與策略模式
- 總結
概述
狀態模式在日常開發中是一個非常實用的模式,可以將你的代碼逼格迅速提升一個檔次,所以讓我們開始今天的卓越之旅吧。
類型
行為型(behavioral)
難度
3顆星
定義
當一個對象內在狀態改變時允許改變其行為,這個對象看起來像是改變了其類。
定義對于初學者沒啥用,因為字都認識卻無法理解其中的含義。必須等學完了,回過頭來看才能更加深刻的理解其含義
使用場景
你發現你的代碼里面存在一個很長的if else列表,而這些分支都是因為不同狀態下執行的操作不一樣時考慮使用此模式
UML類圖
照例先上一張俺手撕的UML類圖
從上圖可見,狀態模式共有3個角色
- State
是一個接口,封裝了狀態及其行為
- ConcreteState X
State的實現類,表示具體的狀態
- Context
保持并切換各個狀態,其持有一個State的引用。它將依賴狀態的各種操作委托給不同的狀態對象執行。其負責與客戶端交互
實例
最近王二狗又要過生日了,近兩年他內心中是非??咕苓^生日的,因為每過一個生日就意味著自己又老一歲,離被辭退的35歲魔咒又近了一步??上r間是不以人的意志為轉移的,任何人都阻止不了時間的流逝,所以該過還的過。令二狗比較欣慰的時,這次過生日老婆送了他一個自己一直想要的機械鍵盤作為生日禮物… 翠花于是在二狗生日前3天在京東上下了一個單…
自從下單以來,二狗天天看物流狀態信息,心心念念著自己的機械鍵盤快點到…
這個物流系統就很適合使用狀態模式來開發,因為此過程存在很多不同的狀態,例如接單,出庫,運輸,送貨,收貨,評價等等。而訂單在每個不同的狀態下的操作可能都不一樣,例如在接單狀態下,商家就需要通知倉庫揀貨,通知用戶等等操作,其他狀態類似
下面是實例的UML類圖
第一,定義一個狀態接口
此接口定義各個狀態的統一操作接口
public interface LogisticsState {void doAction(JdLogistics context); }第二,定義一個物流Context類
此類持有一個LogisticsState 的引用,負責在流程中保持并切換狀態
public class JdLogistics {private LogisticsState logisticsState;public void setLogisticsState(LogisticsState logisticsState) {this.logisticsState = logisticsState;}public LogisticsState getLogisticsState() {return logisticsState;}public void doAction(){Objects.requireNonNull(logisticsState);logisticsState.doAction(this);} }第三,實現各種狀態類
- 接單狀態類,其需要實現LogisticsState接口
- 出庫狀態類
依次類推,可以建立任意多個狀態類
第四, 客戶端使用
public class StateClient {public void buyKeyboard() {//狀態的保持與切換者JdLogistics jdLogistics = new JdLogistics();//接單狀態OrderState orderState = new OrderState();jdLogistics.setLogisticsState(orderState);jdLogistics.doAction();//出庫狀態ProductOutState productOutState = new ProductOutState();jdLogistics.setLogisticsState(productOutState);jdLogistics.doAction();//運輸狀態TransportState transportState = new TransportState();jdLogistics.setLogisticsState(transportState);jdLogistics.doAction();} }輸出結果:
商家已經接單,正在處理中... 商品已經出庫... 商品正在運往天津分發中心可見,我們將每個狀態下要做的具體動作封裝到了每個狀態類中,我們只需要切換不同的狀態即可。如果不使用狀態模式,我們的代碼中可能會出現很長的if else列表,這樣就不便于擴展和修改了。
技術要點總結
- 必須要有一個Context類,這個類持有State接口,負責保持并切換當前的狀態。
- 狀態模式沒有定義在哪里進行狀態轉換,本例是在Context類進行的,也有人在具體的State類中轉換
當使用Context類切換狀態時,狀態類之間互相不認識,他們直接的依賴關系應該由客戶端負責。
例如,只有在接單狀態的操作完成后才應該切換到出庫狀態,那么出庫狀態就對接單狀態有了依賴,這個依賴順序應該由客戶端負責,而不是在狀態內判斷。
當使用具體的State類切換時,狀態直接就可能互相認識,一個狀態執行完就自動切換到了另一個狀態去了
優缺點
優點
- 增強了程序的可擴展性,因為我們很容易添加一個State
- 增強了程序的封裝性,每個狀態的操作都被封裝到了一個狀態類中
缺點
類變多了
狀態模式與策略模式
狀態模式與策略模式的UML類圖都是一樣的,從表面上看他們非常相似。特別是將狀態切換任務放在Context中做的時候就更像了,但是其背后的思想卻非常不同。
- 策略模式定義了一組可互相代替的算法,這一組算法對象完成的是同一個任務,只是使用的方式不同,例如同樣是億萬富翁,馬云通過賣東西實現,而王思聰通過繼承實現。
- 狀態模式不同的狀態完成的任務完全不一樣。
總結
設計模式值得你刻意練習!
最后,如果你從本文中有所收獲,可否點贊轉發支持一下博主,你小小的鼓勵,是激發博主持續寫作的動力…
GitHub源碼地址:design-patterns
總結
以上是生活随笔為你收集整理的秒懂设计模式之状态模式(State Pattern)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 百度-嘟嘟熊买帽子
- 下一篇: lcs算法c语言代码,LCS算法