状态模式
定义
当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。
类型
行为型。
UML类图
角色
- 环境(Context)角色:环境角色含有状态角色的对象,并且可以处理一些请求,这些请求最终产生的响应会与状态相关。
- 状态(State)角色:状态角色定义了每一个状态的行为接口,这些行为将会在
Context
中得以使用。 - 具体状态(ConcreteState)角色:实现了相关行为的具体状态类。
例子
我们看课程视频时,可以播放、加速、暂停视频和停止视频(退出了观看课程视频界面)。
- 当课程视频处于播放状态时,课程视频可以正常播放、加速、暂停、停止。
- 当课程视频处于加速状态时,课程视频可以正常播放、加速、暂停、停止。
- 当课程视频处于暂停状态时,课程视频可以正常播放、加速、暂停、停止。
- 当课程视频处于停止状态时,课程视频可以正常播放、停止,而不能正常加速、暂停。
不用纠结这些规则,只是为了说明当一个对象内在状态改变时允许其改变行为
。
CourseVideoContext类(环境角色),含有状态角色的对象courseVideoState
。
package com.kaven.design.pattern.behavioral.state;
public class CourseVideoContext {
private CourseVideoState courseVideoState;
public final static PlayState PLAY_STATE = new PlayState();
public final static SpeedState SPEED_STATE = new SpeedState();
public final static PauseState PAUSE_STATE = new PauseState();
public final static StopState STOP_STATE = new StopState();
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 pause(){
this.courseVideoState.pause();
}
public void stop(){
this.courseVideoState.stop();
}
}
CourseVideoState类(状态角色),定义了每一个状态的行为接口,这些行为将会在Context
中得以使用,从CourseVideoContext类代码也可以看出来。
package com.kaven.design.pattern.behavioral.state;
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();
}
PlayState类(具体状态角色),播放状态类,继承了CourseVideoState类,实现了对应的行为(根据上面说的规则)。
package com.kaven.design.pattern.behavioral.state;
public class PlayState extends CourseVideoState{
public void play() {
System.out.println("正常播放课程视频状态");
}
public void speed() {
super.courseVideoContext.setCourseVideoState(CourseVideoContext.SPEED_STATE);
}
public void pause() {
super.courseVideoContext.setCourseVideoState(CourseVideoContext.PAUSE_STATE);
}
public void stop() {
super.courseVideoContext.setCourseVideoState(CourseVideoContext.STOP_STATE);
}
}
SpeedState类(具体状态角色),加速状态类,继承了CourseVideoState类,实现了对应的行为(根据上面说的规则)。
package com.kaven.design.pattern.behavioral.state;
public class SpeedState extends CourseVideoState {
public void play() {
super.courseVideoContext.setCourseVideoState(CourseVideoContext.PLAY_STATE);
}
public void speed() {
System.out.println("快进播放课程视频状态");
}
public void pause() {
super.courseVideoContext.setCourseVideoState(CourseVideoContext.PAUSE_STATE);
}
public void stop() {
super.courseVideoContext.setCourseVideoState(CourseVideoContext.STOP_STATE);
}
}
PauseState类(具体状态角色),暂停状态类,继承了CourseVideoState类,实现了对应的行为(根据上面说的规则)。
package com.kaven.design.pattern.behavioral.state;
public class PauseState extends CourseVideoState {
public void play() {
super.courseVideoContext.setCourseVideoState(CourseVideoContext.PLAY_STATE);
}
public void speed() {
super.courseVideoContext.setCourseVideoState(CourseVideoContext.SPEED_STATE);
}
public void pause() {
System.out.println("暂停播放课程视频状态");
}
public void stop() {
super.courseVideoContext.setCourseVideoState(CourseVideoContext.STOP_STATE);
}
}
StopState类(具体状态角色),停止状态类,继承了CourseVideoState类,实现了对应的行为(根据上面说的规则)。
package com.kaven.design.pattern.behavioral.state;
public class StopState extends CourseVideoState {
public void play() {
super.courseVideoContext.setCourseVideoState(CourseVideoContext.PLAY_STATE);
}
public void speed() {
System.out.println("ERROR 停止状态不能快进");
}
public void pause() {
System.out.println("ERROR 停止状态不能暂停");
}
public void stop() {
System.out.println("停止播放课程视频状态");
}
}
应用层代码:
package com.kaven.design.pattern.behavioral.state;
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();
System.out.println("当前状态:"+courseVideoContext.getCourseVideoState().getClass().getSimpleName());
}
}
输出:
当前状态:PlayState
当前状态:PauseState
当前状态:SpeedState
当前状态:StopState
ERROR 停止状态不能快进
当前状态:StopState
好好去理清楚这些代码的逻辑。
这里便完成了一个简单的状态模式的例子。
适用场景
- 行为随状态改变而改变的场景。
- 条件、分支语句的代替者。
优点
- 封装了转换规则。
- 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
- 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
缺点
- 状态模式的使用必然会增加系统类和对象的个数。
- 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
- 状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。
如果有说错的地方,请大家不吝赐教(记得留言哦~~~~)。