【設計模式】狀態模式 ( 簡介 | 適用場景 | 優缺點 | 代碼示例 )
文章目錄
一、狀態模式簡介
二、狀態模式適用場景
三、狀態模式優缺點
四、狀態模式相關設計模式
五、狀態模式代碼示例
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(); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
2、播放狀態類
package state; /** * 視頻的播放狀態 * 可以進行 快進 , 暫停 , 停止 操作 */ public class PlayState extends VedioState{ @Override public void play() { System.out.println("正常播放視頻"); } /** * 暫停時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext * 將上下文 VedioContext 中的狀態 , 設置為 暫停 的狀態即可 */ @Override public void pause() { super.vedioContext.setVedioState(VedioContext.PAUSE_STATE); } /** * 快進時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext * 將上下文 VedioContext 中的狀態 , 設置為 快進 的狀態即可 */ @Override public void speed() { super.vedioContext.setVedioState(VedioContext.SPEED_STATE); } /** * 停止時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext * 將上下文 VedioContext 中的狀態 , 設置為 停止 的狀態即可 */ @Override public void stop() { super.vedioContext.setVedioState(VedioContext.STOP_STATE); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
3、暫停狀態類
package state; /** * 視頻暫停狀態 * 暫停狀態 可以 切換到 播放 , 快進 , 停止 狀態 */ public class PauseState extends VedioState{ /** * 播放時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext * 將上下文 VedioContext 中的狀態 , 設置為 播放 的狀態即可 */ @Override public void play() { super.vedioContext.setVedioState(VedioContext.PLAY_STATE); } /** * 暫停時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext * 將上下文 VedioContext 中的狀態 , 設置為 暫停 的狀態即可 */ @Override public void pause() { System.out.println("暫停播放視頻"); } /** * 快進時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext * 將上下文 VedioContext 中的狀態 , 設置為 快進 的狀態即可 */ @Override public void speed() { super.vedioContext.setVedioState(VedioContext.SPEED_STATE); } /** * 停止時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext * 將上下文 VedioContext 中的狀態 , 設置為 停止 的狀態即可 */ @Override public void stop() { super.vedioContext.setVedioState(VedioContext.STOP_STATE); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
4、快進狀態類
package state; /** * 視頻快進狀態 * 快進狀態下 , 可以進行 播放 , 暫停 , 停止操作 */ public class SpeedState extends VedioState{ /** * 播放時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext * 將上下文 VedioContext 中的狀態 , 設置為 播放 的狀態即可 */ @Override public void play() { super.vedioContext.setVedioState(VedioContext.PLAY_STATE); } /** * 暫停時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext * 將上下文 VedioContext 中的狀態 , 設置為 暫停 的狀態即可 */ @Override public void pause() { System.out.println("快進播放視頻"); } /** * 快進時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext * 將上下文 VedioContext 中的狀態 , 設置為 快進 的狀態即可 */ @Override public void speed() { super.vedioContext.setVedioState(VedioContext.SPEED_STATE); } /** * 停止時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext * 將上下文 VedioContext 中的狀態 , 設置為 停止 的狀態即可 */ @Override public void stop() { super.vedioContext.setVedioState(VedioContext.STOP_STATE); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
5、停止狀態類
package state; /** * 視頻的停止狀態 * 可以進行 播放 操作 * 不能進行 快進 , 暫停 操作 */ public class StopState extends VedioState{ /** * 播放時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext * 將上下文 VedioContext 中的狀態 , 設置為 播放 的狀態即可 */ @Override public void play() { super.vedioContext.setVedioState(VedioContext.PLAY_STATE); } /** * 不能暫停 */ @Override public void pause() { System.out.println("停止狀態不能暫停"); } /** * 不能快進 */ @Override public void speed() { System.out.println("停止狀態不能快進"); } /** * 停止時 , 只需要調用 PlayState 父類 VedioState 的上下文 VedioContext * 將上下文 VedioContext 中的狀態 , 設置為 停止 的狀態即可 */ @Override public void stop() { System.out.println("停止播放視頻"); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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(); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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()); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
執行結果 :
視頻
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。