状态模式
题目描述
在我做这道题目的时候,学习了一下设计模式,于是复习一下!
这道题我是用状态模式写的,那么状态模式是什么呢?
说明:
Context(状态拥有者):是一个具有“状态”属性的类,可以定制相关的接口,让外界能够得知状态的改变或者通过操作让状态改变。
State(状态接口类):制定状态的接口,负责规范Context在特定状态下要表现的行为。
ConcreteState(具体状态类):继承自State, 实现Context在特定状态下该有的行为。
我们可以看出对于上面那道题,我们应该设计一个状态接口State、4个不同状态实现这个接口PlayState、StopState、FastForwardState、FastRewardState,同时在其中设置相应的方法,比如有时候,方法执行之时会改变状态!
代码如下:
类图
(第一次画类图,很多不规范!):
代码如下
创建接口State:
package VideoPlayer;
/**
* @Description:
* @Author: Liu Jianwei
* @Date: 2021/2/28 11:41
*/
public interface State {
void MidClick();
void FastForwardClick();
void FastRewardClick();
}创建四种状态:
package VideoPlayer;
public class PlayState implements State {
private VideoPlayer mVideoPlayer;
public PlayState(VideoPlayer mVideoPlayer) {
this.mVideoPlayer = mVideoPlayer;
}
// 点击中间后,进入待播状态
@Override
public void MidClick() {
System.out.println("已进入待播状态");
mVideoPlayer.setState(mVideoPlayer.mStopState);
}
// 点击快进后 进入快进状态
@Override
public void FastForwardClick() {
System.out.println("已快进");
mVideoPlayer.setState(mVideoPlayer.mFastForwardState);
}
// 点击快退后 进入快退状态
@Override
public void FastRewardClick() {
System.out.println("已快退");
mVideoPlayer.setState(mVideoPlayer.mFastRewardState);
}
}
package VideoPlayer;
public class StopState implements State {
private VideoPlayer mVideoPlay;
public StopState(VideoPlayer mVideoPlay) {
this.mVideoPlay = mVideoPlay;
}
// 点击后 切换到正在播放状态
@Override
public void MidClick() {
System.out.println("正在播放");
mVideoPlay.setState(mVideoPlay.mPlayState);
}
// 暂停状态下点快进 只快进时间 依然暂停
@Override
public void FastForwardClick() {
System.out.println("快进15秒");
}
// 同上
@Override
public void FastRewardClick() {
System.out.println("快退15秒");
}
}
package VideoPlayer;
public class FastForwardState implements State{
private VideoPlayer mVideoPlayer;
public FastForwardState(VideoPlayer mVideoPlayer) {
this.mVideoPlayer = mVideoPlayer;
}
// 暂停
@Override
public void MidClick() {
System.out.println("已进入待播状态");
mVideoPlayer.setState(mVideoPlayer.mStopState);
}
// 点一下返回正常播放状态
@Override
public void FastForwardClick() {
System.out.println("已恢复正常速度");
mVideoPlayer.setState(mVideoPlayer.mPlayState);
}
// 去快退状态
@Override
public void FastRewardClick() {
System.out.println("已快退");
mVideoPlayer.setState(mVideoPlayer.mFastRewardState);
}
}
package VideoPlayer;
public class FastRewardState implements State {
private VideoPlayer mVideoPlayer;
public FastRewardState(VideoPlayer mVideoPlayer) {
this.mVideoPlayer = mVideoPlayer;
}
// 进入暂停
@Override
public void MidClick() {
System.out.println("已进入待播装态");
mVideoPlayer.setState(mVideoPlayer.mStopState);
}
// 进入快进状态
@Override
public void FastForwardClick() {
System.out.println("已进入快进状态");
mVideoPlayer.setState(mVideoPlayer.mFastForwardState);
}
// 快退状态再点快退 会进入到正常播放的状态
@Override
public void FastRewardClick() {
System.out.println("已取消快退");
mVideoPlayer.setState(mVideoPlayer.mPlayState);
}
}主界面:
package VideoPlayer;
public class VideoPlayer {
State mPlayState;
State mStopState;
State mFastForwardState;
State mFastRewardState;
private State state;
// 播放器初始化 为播放状态
public VideoPlayer() {
mPlayState = new PlayState(this);
mStopState = new StopState(this);
mFastForwardState = new FastForwardState(this);
mFastRewardState = new FastRewardState(this);
state = mPlayState;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public void PrintState() {
System.out.println(state);
}
// 中间点击的三个方法实现 播放/暂停、快进、快退
public void MidClick() {
state.MidClick();
}
public void FastForwardClick() {
state.FastForwardClick();
}
public void FastRewardClick() {
state.FastRewardClick();
}
}测试:
package VideoPlayer;
public class MainTest {
public static void main(String[] args) {
VideoPlayer ***ew VideoPlayer();
// 进入待播状态
vp.MidClick();
// 快进
vp.FastForwardClick();
// 快退
vp.FastRewardClick();
}
}总结:
状态模式何时使用呢?
行为随状态改变而改变的场景。比如权限设计,人员的状态不同,即使执行相同的行为,结果也会不同,这种情况下需要考虑用状态模式;在程序中有大量分支和条件判断时,可用状态模式让它通过扩展子类实现条件判断处理。
优缺点
优点:
使用状态模式可以清除地了解某个场景状态执行时所需要配合使用的类对象,并且减少因新增状态而需要大量修改现有程序代码的维护成本。 简言之,使用状态模式能够减少错误并降低维护难度,并且状态执行环境单一化。
缺点:
如果程序中有非常多的场景需要进行状态管理,有可能造成类爆炸,导致后期维护难度上升。