【java_设计模式】状态模式

学习路径: https://coding.imooc.com/class/270.html

  • 前言
    状态模式适用于不同的状态解耦,同时可以定义不同状态的行为、不同状态转换中的行为。

  • 应用场景

/**
     * 测试视频的开始、暂停、停止状态
     * 首次初始化上下文后,视频为开始状态
     * @param args
     */
    public static void main(String[] args) {
        // 上下文给创建出来后,对应的一个状态类也生成
        VideoContext videoContext = new VideoContext(new PlayState());
        videoContext.pause();
        videoContext.pause();
        videoContext.stop();
        videoContext.play();
    }
  • 实现

提供给外层使用的是上下文类VideoContext

/**
 -  只提供上下文给应用层使用,一个上下文对象同一时刻只有一种状态VideoState
 -  值得注意:
 -  1. 所有状态转换都委托给属性VideoState去操作
 -  2. 具体的两个状态的转化产生的逻辑需要到VideoState的子类实现
 */
public class VideoContext {
    // 上下文里面持有状态对象
    private VideoState videoState;
    // 定义常量,所有状态类初始化,目的是给具体的可变状态类拿到不可变的状态对象
    public final static PlayState PLAY_STATE = new PlayState();
    public final static PauseState PAUSE_STATE = new PauseState();
    public final static StopState STOP_STATE = new StopState();

    /**
     * 核心代码
     * new 出来的时候需要指定属性VideoState
     *
     * @param videoState
     */
    public VideoContext(VideoState videoState) {
        this.videoState = videoState;
        // 核心语句
        this.videoState.setVideoContext(this);
    }
    /**
     * 对外提供修改状态的api
     * 底层调用的是videoState的子类
     */
    public void play() { this.videoState.play(); }

    public void pause() { this.videoState.pause(); }

    public void stop() { this.videoState.stop(); }

    public VideoState getVideoState() { return videoState; }
    
    /**
     * 开放给VideoState重设视频状态
     */ 
	public void setVideoState(VideoState videoState) {
        this.videoState = videoState;
        // 核心语句
        this.videoState.setVideoContext(this);
    }
}

内部具体的状态类VideoState的子类

/**
 -  抽象状态类,也持有上下文对象
 -  上下文对象对子类开放,目的是所有子类状态共享一个上下文。
 */
public abstract class VideoState {
    // 子类共享一个上下文,并可以修改
    protected VideoContext videoContext;

    public void setVideoContext(VideoContext videoContext) {
        this.videoContext = videoContext;
    }
    // 所有状态都能转化为任意状态
    public abstract void play();
    public abstract void pause();
    public abstract void stop();
}

子类可以修改上下文状态,并实现各状态转化的逻辑

/**
 -  视频暂停状态
 -  提供不同转态转化后的行为
 */
public class PauseState extends VideoState {
    @Override
    public void play() {
        // 核心语句:子类共享一个上下文资源,修改状态后一定要把上下文中的状态给修改了
        super.videoContext.setVideoState(VideoContext.PLAY_STATE);
        System.out.println("视频状态变化:暂停 --> 开始");
    }

    @Override
    public void pause() {
        System.out.println("视频已暂停,若无响应请稍后再试");
    }

    @Override
    public void stop() {
        super.videoContext.setVideoState(VideoContext.STOP_STATE);
        System.out.println("视频状态变化:暂停 --> 停止");
    }
}
  • 总结
    状态模式的本质是两个类互相持有对方的单个引用,它们在内存中始终是循环指向的。这样的好处是无论切换哪种状态,所在的状态都持有所有状态共享的上下文,也就是所有状态可以互相转化。在VideoContext给new出来的时候通过构造器就实现了VideoState(抽象类)的绑定。如,打开网页视频自动播放,这里就是将上下文的状态一new出来就绑定到PlayState。
	/**
     * 核心代码
     * new 出来的时候需要指定属性VideoState
     *
     * @param videoState 需要一个状态对象指定初始的上下文状态
     */
    public VideoContext(VideoState videoState) {
        this.videoState = videoState;
        // 核心语句
        this.videoState.setVideoContext(this);
    }

在这里插入图片描述
在这里插入图片描述

只暴露VideoContext给外部使用(改变状态),VideoState的子类各自维护切换状态的行为,防止各种状态的代码入侵。并兼顾了状态的拓展。当然,如果要拓展状态,需要同时修改VideoContext和VideoState,只是不会影响行为之间转化的代码。
VideoState是个抽象类,使用多态的特性,运行期可以任意转化为pause、stop、play。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值