狀態模式
- 定義:允許一個對象在其內部狀態改變時,改變它的行為
- 類型:行為型
- 適用場景:一個對象存在多個狀態(不同狀態下行為不同),且狀態可以相互轉換
- 優點:
- 將不同的狀態隔離
- 把各種狀態的轉換邏輯,分布到State的子類中,減少相互間依賴
- 增加新的狀態非常簡單
- 缺點:狀態多的業務場景導致類數目增加,系統變復雜
- 相關設計模式:
- 狀態模式和享元模式:有時候可以配合一起使用,可以使用享元模式在多個上下文角色之間共享這些狀態實例
Coding
public class CourseVideoContext { private CourseVideoState courseVideoState; public final static PlayState PLAY_STATE = new PlayState(); public final static StopState STOP_STATE = new StopState(); public final static PauseState PAUSE_STATE = new PauseState(); public final static SpeedState SPEED_STATE = new SpeedState(); public CourseVideoState getCourseVideoState() { return courseVideoState; } public void setCourseVideoState(CourseVideoState courseVideoState) { this.courseVideoState = courseVideoState; this.courseVideoState.setCourseVideoContext(this); } public void play() { this.courseVideoState.play(); } public void speed() { this.courseVideoState.speed(); } public void stop() { this.courseVideoState.stop(); } public void pause() { this.courseVideoState.pause(); } } /** * 課程視頻狀態抽象類 */ public abstract class CourseVideoState { protected CourseVideoContext courseVideoContext; public void setCourseVideoContext(CourseVideoContext courseVideoContext) { this.courseVideoContext = courseVideoContext; } public abstract void play(); public abstract void speed(); public abstract void pause(); public abstract void stop(); } /** * 暫停狀態 */ public class PauseState extends CourseVideoState { @Override public void play() { super.courseVideoContext.setCourseVideoState(CourseVideoContext.PLAY_STATE); } @Override public void speed() { super.courseVideoContext.setCourseVideoState(CourseVideoContext.SPEED_STATE); } @Override public void pause() { System.out.println("暫停播放課程視頻狀態"); } @Override public void stop() { super.courseVideoContext.setCourseVideoState(CourseVideoContext.STOP_STATE); } } /** * 播放狀態 */ public class PlayState extends CourseVideoState { @Override public void play() { System.out.println("正常播放課程視頻狀態"); } @Override public void speed() { super.courseVideoContext.setCourseVideoState(CourseVideoContext.SPEED_STATE); } @Override public void pause() { super.courseVideoContext.setCourseVideoState(CourseVideoContext.PAUSE_STATE); } @Override public void stop() { super.courseVideoContext.setCourseVideoState(CourseVideoContext.STOP_STATE); } } /** * 快放狀態 */ public class SpeedState extends CourseVideoState { @Override public void play() { super.courseVideoContext.setCourseVideoState(CourseVideoContext.PLAY_STATE); } @Override public void speed() { System.out.println("快進播放課程視頻狀態"); } @Override public void pause() { super.courseVideoContext.setCourseVideoState(CourseVideoContext.PAUSE_STATE); } @Override public void stop() { super.courseVideoContext.setCourseVideoState(CourseVideoContext.STOP_STATE); } } /** * 停止狀態 */ public class StopState extends CourseVideoState { @Override public void play() { super.courseVideoContext.setCourseVideoState(CourseVideoContext.PLAY_STATE); } @Override public void speed() { System.out.println("ERROR 停止狀態不能快進!!"); } @Override public void pause() { System.out.println("ERROR 停止狀態不能暫停!!"); } @Override public void stop() { System.out.println("停止播放課程視頻狀態"); } }
UML

測試
public class Test { public static void main(String[] args) { CourseVideoContext courseVideoContext = new CourseVideoContext(); courseVideoContext.setCourseVideoState(new PlayState()); System.out.println("當前狀態:" + courseVideoContext.getCourseVideoState().getClass().getSimpleName()); courseVideoContext.pause(); System.out.println("當前狀態:" + courseVideoContext.getCourseVideoState().getClass().getSimpleName()); courseVideoContext.speed(); System.out.println("當前狀態:" + courseVideoContext.getCourseVideoState().getClass().getSimpleName()); courseVideoContext.stop(); System.out.println("當前狀態:" + courseVideoContext.getCourseVideoState().getClass().getSimpleName()); courseVideoContext.speed(); } } ========輸出======= 當前狀態:PlayState 當前狀態:PauseState 當前狀態:SpeedState 當前狀態:StopState ERROR 停止狀態不能快進!!
源碼中的應用
在一些業務場景中可以用狀態模式,比如不同電商網站關于訂單扭轉的狀態,可以自己設置一個和業務場景非常契合的狀態機,還有一些比如我們的例子視頻狀態扭轉、辦公系統流程上的扭轉等等都是和具體的業務場景相關的,可以使用上狀態模式

浙公網安備 33010602011771號