状态模式
- 定义:允许一个对象在其内部状态改变时,改变它的行为
- 类型:行为型
- 适用场景:一个对象存在多个状态(不同状态下行为不同),且状态可以相互转换
- 优点:
- 将不同的状态隔离
- 把各种状态的转换逻辑,分布到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 停止状态不能快进!!
源码中的应用
在一些业务场景中可以用状态模式,比如不同电商网站关于订单扭转的状态,可以自己设置一个和业务场景非常契合的状态机,还有一些比如我们的例子视频状态扭转、办公系统流程上的扭转等等都是和具体的业务场景相关的,可以使用上状态模式