【设计模式】状态模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
文章目錄
- 一、狀態模式簡介
- 二、狀態模式適用場景
- 三、狀態模式優缺點
- 四、狀態模式相關設計模式
- 五、狀態模式代碼示例
- 1、狀態類父類
- 2、播放狀態類
- 3、暫停狀態類
- 4、快進狀態類
- 5、停止狀態類
- 6、上下文控制類
- 7、測試
一、狀態模式簡介
狀態模式 : 允許 對象 在 內部狀態 改變時 , 改變它的行為 ;
一個對象 , 如果其 內部狀態改變 , 其 行為也需要進行改變 ; 如果其行為不需要改變 , 也可以只 控制 該對象的狀態 的 互相轉換 ;
當控制一個對象 , 其狀態轉換過程比較復雜時 , 將 狀態判斷邏輯 , 轉到代表不同狀態的一系列類中 ;
如 : 引入 視頻播放 的業務場景 , 播放器有 初始狀態 , 播放狀態 , 暫停狀態 , 停止狀態 , 快進狀態 等多種狀態 , 將這些 狀態 都封裝到 代表不同狀態的類 中 , 可以將復雜的判斷邏輯簡化 , 將這些 邏輯 擴展到不同的狀態類中 ;
狀態模式類型 : 行為型 ;
二、狀態模式適用場景
狀態模式適用場景 : 一個對象 , 存在多個狀態 , 狀態可以相互轉換 ; 不同狀態下 , 行為不同 ;
不同狀態下 , 行為不同的示例 , 如 :
購買物品 , 將物品放入購物車并生成訂單 , 可以進行付款 ; 如果 訂單 超過 24 小時后 , 被關閉訂單 , 此時訂單取消 , 無法付款 ;
電梯運行時 , 不能開門 ; 電梯停止后 , 才能開門 ;
三、狀態模式優缺點
狀態模式優點 :
可以將 不同的狀態 隔離 ; 每個狀態都是一個單獨的類 ;
可以將 各種狀態 的 轉換邏輯 , 分布到 狀態 的子類中 , 減少相互依賴 ;
增加 新狀態 , 操作簡單 ;
狀態模式缺點 :
如果 狀態數量 比較多 , 狀態類 的 數量會增加 , 業務場景系統變得很復雜 ; 如果業務中某個對象由幾十上百個狀態 , 就會很復雜 , 這時就需要對狀態進行拆分處理 ;
四、狀態模式相關設計模式
狀態模式 與 享元模式 , 可以配合在一起使用 , 可以使用享元模式 , 在多個上下文中 , 共享狀態實例 ;
五、狀態模式代碼示例
業務場景 :
視頻播放器 , 有 : 暫停 , 播放 , 快進 , 停止 , 四個狀態 ;
在 停止 狀態下 , 無法快進 , 如果當前是 停止 狀態 , 此時要轉為 快進 狀態 , 需要進行校驗 ;
- 如果不使用 狀態模式 , 則需要進行 if else 判斷 ;
- 如果使用 狀態模式 , 就很容易實現 ;
狀態類 :
- 定義狀態父類抽象類 , 抽象方法是各個狀態對應的方法 ;
- 定義狀態子類 , 每個狀態對應一個子類對象 ;
上下文類 :
- 在該類中封裝 所有的狀態實例 , 以及定義 狀態改變方法 ;
- 封裝當前狀態類 , 狀態改變方法 調用時 , 實際上調用的是 當前狀態類的 對應方法 ;
1、狀態類父類
package state;/*** 視頻狀態 父類* 所有的視頻狀態 , 都要繼承該類*/ public abstract class VedioState {/*** 視頻播放上下文* 聲明為 protected , 子類可以拿到該成員變量*/protected VedioContext vedioContext;public void setVedioContext(VedioContext vedioContext) {this.vedioContext = vedioContext;}/*** 播放* 對應播放狀態*/public abstract void play();/*** 停止* 對應停止狀態*/public abstract void pause();/*** 快進* 對應快進狀態*/public abstract void speed();/*** 停止* 對應停止狀態*/public abstract void stop(); }
2、播放狀態類
package state;/*** 視頻的播放狀態* 可以進行 快進 , 暫停 , 停止 操作*/ public class PlayState extends VedioState{@Overridepublic void play() {System.out.println("正常播放視頻");}/*** 暫停時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext* 將上下文 VedioContext 中的狀態 , 設置為 暫停 的狀態即可*/@Overridepublic void pause() {super.vedioContext.setVedioState(VedioContext.PAUSE_STATE);}/*** 快進時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext* 將上下文 VedioContext 中的狀態 , 設置為 快進 的狀態即可*/@Overridepublic void speed() {super.vedioContext.setVedioState(VedioContext.SPEED_STATE);}/*** 停止時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext* 將上下文 VedioContext 中的狀態 , 設置為 停止 的狀態即可*/@Overridepublic void stop() {super.vedioContext.setVedioState(VedioContext.STOP_STATE);} }
3、暫停狀態類
package state;/*** 視頻暫停狀態* 暫停狀態 可以 切換到 播放 , 快進 , 停止 狀態*/ public class PauseState extends VedioState{/*** 播放時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext* 將上下文 VedioContext 中的狀態 , 設置為 播放 的狀態即可*/@Overridepublic void play() {super.vedioContext.setVedioState(VedioContext.PLAY_STATE);}/*** 暫停時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext* 將上下文 VedioContext 中的狀態 , 設置為 暫停 的狀態即可*/@Overridepublic void pause() {System.out.println("暫停播放視頻");}/*** 快進時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext* 將上下文 VedioContext 中的狀態 , 設置為 快進 的狀態即可*/@Overridepublic void speed() {super.vedioContext.setVedioState(VedioContext.SPEED_STATE);}/*** 停止時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext* 將上下文 VedioContext 中的狀態 , 設置為 停止 的狀態即可*/@Overridepublic void stop() {super.vedioContext.setVedioState(VedioContext.STOP_STATE);} }
4、快進狀態類
package state;/*** 視頻快進狀態* 快進狀態下 , 可以進行 播放 , 暫停 , 停止操作*/ public class SpeedState extends VedioState{/*** 播放時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext* 將上下文 VedioContext 中的狀態 , 設置為 播放 的狀態即可*/@Overridepublic void play() {super.vedioContext.setVedioState(VedioContext.PLAY_STATE);}/*** 暫停時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext* 將上下文 VedioContext 中的狀態 , 設置為 暫停 的狀態即可*/@Overridepublic void pause() {System.out.println("快進播放視頻");}/*** 快進時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext* 將上下文 VedioContext 中的狀態 , 設置為 快進 的狀態即可*/@Overridepublic void speed() {super.vedioContext.setVedioState(VedioContext.SPEED_STATE);}/*** 停止時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext* 將上下文 VedioContext 中的狀態 , 設置為 停止 的狀態即可*/@Overridepublic void stop() {super.vedioContext.setVedioState(VedioContext.STOP_STATE);} }
5、停止狀態類
package state;/*** 視頻的停止狀態* 可以進行 播放 操作* 不能進行 快進 , 暫停 操作*/ public class StopState extends VedioState{/*** 播放時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext* 將上下文 VedioContext 中的狀態 , 設置為 播放 的狀態即可*/@Overridepublic void play() {super.vedioContext.setVedioState(VedioContext.PLAY_STATE);}/*** 不能暫停*/@Overridepublic void pause() {System.out.println("停止狀態不能暫停");}/*** 不能快進*/@Overridepublic void speed() {System.out.println("停止狀態不能快進");}/*** 停止時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext* 將上下文 VedioContext 中的狀態 , 設置為 停止 的狀態即可*/@Overridepublic void stop() {System.out.println("停止播放視頻");} }
6、上下文控制類
package state;/*** 使用享元模式 , 共享同一個對象** 上下文也有 play , pause , speed , stop 等狀態* 執行這些方法時 , 調用狀態的相應方法*/ public class VedioContext {/*** 當前的狀態*/private VedioState mVedioState;public final static PlayState PLAY_STATE = new PlayState();public final static PauseState PAUSE_STATE = new PauseState();public final static SpeedState SPEED_STATE = new SpeedState();public final static StopState STOP_STATE = new StopState();public VedioState getVedioState() {return mVedioState;}/*** 將傳入的 VedioState , 賦值給當前的 VedioState mVedioState 成員* 除此之外 , 還要設置 VedioState 的上下文 , 即該類本身* 將當前的環境 VedioContext , 通知到各個狀態實現類* @param mVedioState*/public void setVedioState(VedioState mVedioState) {this.mVedioState = mVedioState;this.mVedioState.setVedioContext(this);}public void play() {this.mVedioState.play();}public void pause() {this.mVedioState.pause();}public void speed() {this.mVedioState.speed();}public void stop() {this.mVedioState.stop();} }
7、測試
package state;public class Main {public static void main(String[] args) {VedioContext vedioContext = new VedioContext();vedioContext.setVedioState(VedioContext.PLAY_STATE);System.out.println("當前視頻狀態 : " + vedioContext.getVedioState().getClass().getSimpleName());vedioContext.pause();System.out.println("當前視頻狀態 : " + vedioContext.getVedioState().getClass().getSimpleName());vedioContext.speed();System.out.println("當前視頻狀態 : " + vedioContext.getVedioState().getClass().getSimpleName());vedioContext.stop();System.out.println("當前視頻狀態 : " + vedioContext.getVedioState().getClass().getSimpleName());vedioContext.speed();System.out.println("當前視頻狀態 : " + vedioContext.getVedioState().getClass().getSimpleName());} }
執行結果 :
總結
以上是生活随笔為你收集整理的【设计模式】状态模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【设计模式】访问者模式 ( 简介 | 适
- 下一篇: 【设计模式】中介者模式 ( 简介 | 适