文章目录

  • 一、状态模式简介
  • 二、状态模式适用场景
  • 三、状态模式优缺点
  • 四、状态模式相关设计模式
  • 五、状态模式代码示例
    • 1、状态类父类
    • 2、播放状态类
    • 3、暂停状态类
    • 4、快进状态类
    • 5、停止状态类
    • 6、上下文控制类
    • 7、测试

一、状态模式简介


状态模式 : 允许 对象 在 内部状态 改变时 , 改变它的行为 ;

一个对象 , 如果其 内部状态改变 , 其 行为也需要进行改变 ; 如果其行为不需要改变 , 也可以只 控制 该对象的状态 的 互相转换 ;

当控制一个对象 , 其状态转换过程比较复杂时 , 将 状态判断逻辑 , 转到代表不同状态的一系列类中 ;

如 : 引入 视频播放 的业务场景 , 播放器有 初始状态 , 播放状态 , 暂停状态 , 停止状态 , 快进状态 等多种状态 , 将这些 状态 都封装到 代表不同状态的类 中 , 可以将复杂的判断逻辑简化 , 将这些 逻辑 扩展到不同的状态类中 ;

状态模式类型 : 行为型 ;

二、状态模式适用场景


状态模式适用场景 : 一个对象 , 存在多个状态 , 状态可以相互转换 ; 不同状态下 , 行为不同 ;

不同状态下 , 行为不同的示例 , 如 :

购买物品 , 将物品放入购物车并生成订单 , 可以进行付款 ; 如果 订单 超过 24 小时后 , 被关闭订单 , 此时订单取消 , 无法付款 ;

电梯运行时 , 不能开门 ; 电梯停止后 , 才能开门 ;

三、状态模式优缺点


状态模式优点 :

可以将 不同的状态 隔离 ; 每个状态都是一个单独的类 ;

可以将 各种状态 的 转换逻辑 , 分布到 状态 的子类中 , 减少相互依赖 ;

增加 新状态 , 操作简单 ;

状态模式缺点 :

如果 状态数量 比较多 , 状态类 的 数量会增加 , 业务场景系统变得很复杂 ; 如果业务中某个对象由几十上百个状态 , 就会很复杂 , 这时就需要对状态进行拆分处理 ;

四、状态模式相关设计模式


状态模式 与 享元模式 , 可以配合在一起使用 , 可以使用享元模式 , 在多个上下文中 , 共享状态实例 ;

五、状态模式代码示例


业务场景 :

视频播放器 , 有 : 暂停 , 播放 , 快进 , 停止 , 四个状态 ;

在 停止 状态下 , 无法快进 , 如果当前是 停止 状态 , 此时要转为 快进 状态 , 需要进行校验 ;

  • 如果不使用 状态模式 , 则需要进行 if else 判断 ;
  • 如果使用 状态模式 , 就很容易实现 ;

状态类 :

  • 定义状态父类抽象类 , 抽象方法是各个状态对应的方法 ;
  • 定义状态子类 , 每个状态对应一个子类对象 ;

上下文类 :

  • 在该类中封装 所有的状态实例 , 以及定义 状态改变方法 ;
  • 封装当前状态类 , 状态改变方法 调用时 , 实际上调用的是 当前状态类的 对应方法 ;

1、状态类父类

package state;/*** 视频状态 父类*      所有的视频状态 , 都要继承该类*/
public abstract class VedioState {/*** 视频播放上下文*      声明为 protected , 子类可以拿到该成员变量*/protected VedioContext vedioContext;public void setVedioContext(VedioContext vedioContext) {this.vedioContext = vedioContext;}/*** 播放*      对应播放状态*/public abstract void play();/*** 停止*      对应停止状态*/public abstract void pause();/*** 快进*      对应快进状态*/public abstract void speed();/*** 停止*      对应停止状态*/public abstract void stop();
}

2、播放状态类

package state;/*** 视频的播放状态*      可以进行 快进 , 暂停 , 停止 操作*/
public class PlayState extends VedioState{@Overridepublic void play() {System.out.println("正常播放视频");}/*** 暂停时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext*      将上下文 VedioContext 中的状态 , 设置为 暂停 的状态即可*/@Overridepublic void pause() {super.vedioContext.setVedioState(VedioContext.PAUSE_STATE);}/*** 快进时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext*      将上下文 VedioContext 中的状态 , 设置为 快进 的状态即可*/@Overridepublic void speed() {super.vedioContext.setVedioState(VedioContext.SPEED_STATE);}/*** 停止时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext*      将上下文 VedioContext 中的状态 , 设置为 停止 的状态即可*/@Overridepublic void stop() {super.vedioContext.setVedioState(VedioContext.STOP_STATE);}
}

3、暂停状态类

package state;/*** 视频暂停状态*      暂停状态 可以 切换到 播放 , 快进 , 停止 状态*/
public class PauseState extends VedioState{/*** 播放时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext*      将上下文 VedioContext 中的状态 , 设置为 播放 的状态即可*/@Overridepublic void play() {super.vedioContext.setVedioState(VedioContext.PLAY_STATE);}/*** 暂停时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext*      将上下文 VedioContext 中的状态 , 设置为 暂停 的状态即可*/@Overridepublic void pause() {System.out.println("暂停播放视频");}/*** 快进时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext*      将上下文 VedioContext 中的状态 , 设置为 快进 的状态即可*/@Overridepublic void speed() {super.vedioContext.setVedioState(VedioContext.SPEED_STATE);}/*** 停止时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext*      将上下文 VedioContext 中的状态 , 设置为 停止 的状态即可*/@Overridepublic void stop() {super.vedioContext.setVedioState(VedioContext.STOP_STATE);}
}

4、快进状态类

package state;/*** 视频快进状态*      快进状态下 , 可以进行 播放 , 暂停 , 停止操作*/
public class SpeedState extends VedioState{/*** 播放时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext*      将上下文 VedioContext 中的状态 , 设置为 播放 的状态即可*/@Overridepublic void play() {super.vedioContext.setVedioState(VedioContext.PLAY_STATE);}/*** 暂停时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext*      将上下文 VedioContext 中的状态 , 设置为 暂停 的状态即可*/@Overridepublic void pause() {System.out.println("快进播放视频");}/*** 快进时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext*      将上下文 VedioContext 中的状态 , 设置为 快进 的状态即可*/@Overridepublic void speed() {super.vedioContext.setVedioState(VedioContext.SPEED_STATE);}/*** 停止时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext*      将上下文 VedioContext 中的状态 , 设置为 停止 的状态即可*/@Overridepublic void stop() {super.vedioContext.setVedioState(VedioContext.STOP_STATE);}
}

5、停止状态类

package state;/*** 视频的停止状态*      可以进行 播放 操作*      不能进行 快进 , 暂停 操作*/
public class StopState extends VedioState{/*** 播放时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext*      将上下文 VedioContext 中的状态 , 设置为 播放 的状态即可*/@Overridepublic void play() {super.vedioContext.setVedioState(VedioContext.PLAY_STATE);}/*** 不能暂停*/@Overridepublic void pause() {System.out.println("停止状态不能暂停");}/*** 不能快进*/@Overridepublic void speed() {System.out.println("停止状态不能快进");}/*** 停止时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext*      将上下文 VedioContext 中的状态 , 设置为 停止 的状态即可*/@Overridepublic void stop() {System.out.println("停止播放视频");}
}

6、上下文控制类

package state;/*** 使用享元模式 , 共享同一个对象** 上下文也有 play , pause , speed , stop 等状态*      执行这些方法时 , 调用状态的相应方法*/
public class VedioContext {/*** 当前的状态*/private VedioState mVedioState;public final static PlayState PLAY_STATE = new PlayState();public final static PauseState PAUSE_STATE = new PauseState();public final static SpeedState SPEED_STATE = new SpeedState();public final static StopState STOP_STATE = new StopState();public VedioState getVedioState() {return mVedioState;}/*** 将传入的 VedioState , 赋值给当前的 VedioState mVedioState 成员*      除此之外 , 还要设置 VedioState 的上下文 , 即该类本身*      将当前的环境 VedioContext , 通知到各个状态实现类* @param mVedioState*/public void setVedioState(VedioState mVedioState) {this.mVedioState = mVedioState;this.mVedioState.setVedioContext(this);}public void play() {this.mVedioState.play();}public void pause() {this.mVedioState.pause();}public void speed() {this.mVedioState.speed();}public void stop() {this.mVedioState.stop();}
}

7、测试

package state;public class Main {public static void main(String[] args) {VedioContext vedioContext = new VedioContext();vedioContext.setVedioState(VedioContext.PLAY_STATE);System.out.println("当前视频状态 : " + vedioContext.getVedioState().getClass().getSimpleName());vedioContext.pause();System.out.println("当前视频状态 : " + vedioContext.getVedioState().getClass().getSimpleName());vedioContext.speed();System.out.println("当前视频状态 : " + vedioContext.getVedioState().getClass().getSimpleName());vedioContext.stop();System.out.println("当前视频状态 : " + vedioContext.getVedioState().getClass().getSimpleName());vedioContext.speed();System.out.println("当前视频状态 : " + vedioContext.getVedioState().getClass().getSimpleName());}
}

执行结果 :

【设计模式】状态模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )相关推荐

  1. 【设计模式】策略模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

    文章目录 一.策略模式简介 二.策略模式适用场景 三.策略模式优缺点 四.策略模式与其它设计模式 五.策略模式代码示例 1.促销策略接口 2.满减促销策略 3.返现促销策略 4.空促销策略 5.促销策 ...

  2. 【设计模式】模板方法模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

    文章目录 一.模板方法模式简介 二.模板方法模式适用场景 三.模板方法模式优缺点 四.模板方法扩展 五.模板方法模式相关设计模式 六.模板方法模式代码示例 1.模板方法抽象类 2.模板方法实现类 1 ...

  3. 【设计模式】备忘录模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

    文章目录 一.备忘录模式简介 二.备忘录模式 适用场景 三.备忘录模式 优缺点 四.备忘录模式 与 状态模式 五.备忘录模式 代码示例 1.文档类 2.文档备忘录类 3.文档备忘录管理类 4.测试类 ...

  4. 【设计模式】中介者模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

    文章目录 一.中介者模式简介 二.中介者模式适用场景 三.中介者模式优缺点 四.中介者模式 与 观察者模式 五.中介者模式 代码示例 1.聊天室 2.用户 3.运行实例 一.中介者模式简介 中介者模式 ...

  5. 【设计模式】访问者模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

    文章目录 一.访问者模式简介 二.访问者模式 适用场景 三.访问者模式 优缺点 四.访问者模式 与 迭代器模式 五.代码示例 1.Game 父类 ( 被访问者 ) 2.VipGame 收费游戏 ( 被 ...

  6. 【设计模式】责任链模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

    文章目录 一.责任链模式简介 二.责任链模式相关设计模式 三.责任链模式 代码示例 1.用户账户类 2.校验器父类 3.用户名校验器 4.密码校验器 5.电话号码校验器 6.运行测试 一.责任链模式简 ...

  7. 【设计模式】桥接模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

    文章目录 一.桥接模式简介 二.桥接模式适用场景 三.桥接模式优缺点 四.桥接模式相关设计模式 五.桥接模式代码示例 1.视频格式抽象 2.FLV 视频格式实现 3.MP4 视频格式实现 4.系统平台 ...

  8. 【设计模式】工厂方法模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

    文章目录 一.工厂方法模式简介 二.工厂方法模式适用场景 三.工厂方法模式优缺点 四.工厂方法模式代码示例 1.产品抽象类 2.产品实现类 1 3.产品实现类 2 4.抽象工厂类 5.实现工厂类 1 ...

  9. 【设计模式】解释器模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

    文章目录 一.解释器模式简介 二.解释器模式适用场景 三.解释器模式优缺点 四.解释器模式与适配器模式 五.解释器模式代码示例 1.解释器接口 2.加法解释器 3.乘法解释器 4.整型解释器 5.语法 ...

最新文章

  1. 【数据结构】顺序串的插入算法,删除算法,连接运算,顺序串求子串算法
  2. 数据库设计三大范式应用实例剖析(转载)
  3. urllib的实现---cookie处理
  4. 模型融合(stackingblending)
  5. 几个方便编程的C++特性
  6. 一起谈.NET技术,Visual Studio自定义调试窗体两个小技巧
  7. 2.1.1Remove Duplicates from Sorted Arr
  8. js实现的笛卡尔乘积-商品发布
  9. Linux下数学(科学)软件简介(一)
  10. 给刚做网站不久的草根站长们
  11. sonar 加载mysql_sonar安装配置
  12. RRC 常用名词解释
  13. 训练集,验证集,测试集
  14. 汽车故障诊断技术【1】
  15. Mac电脑无法从Photoshop 2020作为插件访问DeNoise AI的解决办法
  16. 滴滴翻译技术探索与实践
  17. HTML期末大作业~海贼王动漫的HTML网页制作(共五页有五种风格)
  18. MYSQL设置初始密码
  19. 电脑城 Ghost XP SP3 笔记本专用版 2012.10
  20. 银海系统服务器登录不上,解决登录问题 - Skype for Business | Microsoft Docs

热门文章

  1. 两道相似题——water-easyJavabeans
  2. 推荐些在线小制作小工具
  3. 【专题六】虚拟化实施人才和培训的瓶颈如何解决? ——虚拟化人才逆势抢手 5项技能最关键...
  4. 后盾网lavarel视频项目---lavarel中间件(使用中间件拦截没登录的用户)
  5. legend3---阿里云如何多个域名指向同一个网站
  6. 04:网络层协议介绍
  7. I think i need a houseboot C语言 UVA2363
  8. 自动生成Hibernate框架结构
  9. echart封装,前端简单路由,图表设置自动化
  10. 关于12月28日到12月29日