【设计模式】状态模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
文章目录
- 一、状态模式简介
- 二、状态模式适用场景
- 三、状态模式优缺点
- 四、状态模式相关设计模式
- 五、状态模式代码示例
- 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.促销策略接口 2.满减促销策略 3.返现促销策略 4.空促销策略 5.促销策 ...
- 【设计模式】模板方法模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
文章目录 一.模板方法模式简介 二.模板方法模式适用场景 三.模板方法模式优缺点 四.模板方法扩展 五.模板方法模式相关设计模式 六.模板方法模式代码示例 1.模板方法抽象类 2.模板方法实现类 1 ...
- 【设计模式】备忘录模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
文章目录 一.备忘录模式简介 二.备忘录模式 适用场景 三.备忘录模式 优缺点 四.备忘录模式 与 状态模式 五.备忘录模式 代码示例 1.文档类 2.文档备忘录类 3.文档备忘录管理类 4.测试类 ...
- 【设计模式】中介者模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
文章目录 一.中介者模式简介 二.中介者模式适用场景 三.中介者模式优缺点 四.中介者模式 与 观察者模式 五.中介者模式 代码示例 1.聊天室 2.用户 3.运行实例 一.中介者模式简介 中介者模式 ...
- 【设计模式】访问者模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
文章目录 一.访问者模式简介 二.访问者模式 适用场景 三.访问者模式 优缺点 四.访问者模式 与 迭代器模式 五.代码示例 1.Game 父类 ( 被访问者 ) 2.VipGame 收费游戏 ( 被 ...
- 【设计模式】责任链模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
文章目录 一.责任链模式简介 二.责任链模式相关设计模式 三.责任链模式 代码示例 1.用户账户类 2.校验器父类 3.用户名校验器 4.密码校验器 5.电话号码校验器 6.运行测试 一.责任链模式简 ...
- 【设计模式】桥接模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
文章目录 一.桥接模式简介 二.桥接模式适用场景 三.桥接模式优缺点 四.桥接模式相关设计模式 五.桥接模式代码示例 1.视频格式抽象 2.FLV 视频格式实现 3.MP4 视频格式实现 4.系统平台 ...
- 【设计模式】工厂方法模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
文章目录 一.工厂方法模式简介 二.工厂方法模式适用场景 三.工厂方法模式优缺点 四.工厂方法模式代码示例 1.产品抽象类 2.产品实现类 1 3.产品实现类 2 4.抽象工厂类 5.实现工厂类 1 ...
- 【设计模式】解释器模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
文章目录 一.解释器模式简介 二.解释器模式适用场景 三.解释器模式优缺点 四.解释器模式与适配器模式 五.解释器模式代码示例 1.解释器接口 2.加法解释器 3.乘法解释器 4.整型解释器 5.语法 ...
最新文章
- 【数据结构】顺序串的插入算法,删除算法,连接运算,顺序串求子串算法
- 数据库设计三大范式应用实例剖析(转载)
- urllib的实现---cookie处理
- 模型融合(stackingblending)
- 几个方便编程的C++特性
- 一起谈.NET技术,Visual Studio自定义调试窗体两个小技巧
- 2.1.1Remove Duplicates from Sorted Arr
- js实现的笛卡尔乘积-商品发布
- Linux下数学(科学)软件简介(一)
- 给刚做网站不久的草根站长们
- sonar 加载mysql_sonar安装配置
- RRC 常用名词解释
- 训练集,验证集,测试集
- 汽车故障诊断技术【1】
- Mac电脑无法从Photoshop 2020作为插件访问DeNoise AI的解决办法
- 滴滴翻译技术探索与实践
- HTML期末大作业~海贼王动漫的HTML网页制作(共五页有五种风格)
- MYSQL设置初始密码
- 电脑城 Ghost XP SP3 笔记本专用版 2012.10
- 银海系统服务器登录不上,解决登录问题 - Skype for Business | Microsoft Docs