【软考】设计模式之状态模式

目录

        • 1. 说明
        • 2. 应用场景
        • 3. 结构图
        • 4. 构成
        • 5. 优缺点
          • 5.1 优点
          • 5.2 缺点
        • 6. java示例
          • 6.1 非状态模式
            • 6.1.1 问题分析
            • 6.1.2 接口类
            • 6.1.2 实现类
            • 6.1.3 客户端
            • 6.1.4 结果截图
          • 6.2 状态模式
            • 6.2.1 抽象状态类
            • 6.2.2 状态类
            • 6.2.3 上下文类
            • 6.2.4 上下文类

1. 说明
  • 1.允许一个对象在其内部状态改变时改变它的行为。
  • 2.对象看起来似乎修改了它的类。
  • 3.对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。
2. 应用场景
  • 1.一个对象的行为决定于它的状态,并且它必须在运行时刻根据状态改变它的行为。
  • 2.一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。State模式将每一个条件分支放入一个独立的类中。这使得开发者可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象独立变化。
3. 结构图

在这里插入图片描述

4. 构成
  • 1.环境角色:Context(上下文)定义客户端感兴趣的接口;维护一个ConcreteState子类的实例,这个实例定义当前状态
  • 2.抽象状态角色:State(状态)定义一个接口以封装与Context的一个特定状态相关的行为
  • 3.具体状态角色:ConcreteState(具体状态子类)每个子类实现与Context的一个状态相关的行为
5. 优缺点
5.1 优点
  • 1.将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
  • 2.允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
5.2 缺点
  • 1.状态模式的使用必然会增加系统类和对象的个数。
  • 2.状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
  • 3.状态模式对"开闭原则"的支持并不太好。
6. java示例
6.1 非状态模式
6.1.1 问题分析
  • 1.使用了大量的switch case这样的判断(if else也是一样),使程序的可阅读性变差
  • 2.扩展性差,如果新加了一种状态,则需要修改判断逻辑
6.1.2 接口类
package com.learning.state.before;/*** 电梯接口*/
public interface ILift {//定义四个电梯状态的常量/*** 打开状态*/int OPENING_STATE = 1;/*** 关闭状态*/int CLOSING_STATE = 2;/*** 运行状态*/int RUNNING_STATE = 3;/*** 停止状态*/int STOPPING_STATE = 4;//设置电梯状态的功能void setState(int state);//电梯操作功能void open();//电梯关闭功能void close();//电梯运行功能void run();//电梯停止功能void stop();
}
6.1.2 实现类
package com.learning.state.before;/*** @Description 电梯类**/
public class Lift implements ILift{//当前电梯状态private int state;@Overridepublic void setState(int state) {this.state = state;}@Overridepublic void open() {switch(state){//如果当前电梯状态是开启状态case OPENING_STATE://什么都不做break;//如果当前电梯状态是关闭状态,打开电梯case CLOSING_STATE:System.out.println("电梯打开了");// 设置当前电梯状态为开启状态setState(OPENING_STATE);break;//如果当前电梯状态是运行状态case RUNNING_STATE://什么都不做break;//如果当前电梯状态是开启状态,打开电梯case STOPPING_STATE:System.out.println("电梯打开了");setState(OPENING_STATE);break;}}@Overridepublic void close() {switch(this.state) {case OPENING_STATE://只有开门状态可以关闭电梯门System.out.println("电梯关门了");//关门之后电梯就是关闭状态了this.setState(CLOSING_STATE);break;case CLOSING_STATE://已经是关门状态,不能关门//什么都不做break;case RUNNING_STATE://运行时电梯门是关着的,不能关门//什么都不做break;case STOPPING_STATE://停止时电梯也是关着的,不能关门//什么都不做break;}}@Overridepublic void run() {switch(this.state) {case OPENING_STATE://电梯不能开着门运行break;case CLOSING_STATE://门关了,可以运行了System.out.println("电梯运行了");//设置为运行状态this.setState(RUNNING_STATE);break;case RUNNING_STATE://已经是运行状态了break;case STOPPING_STATE:System.out.println("电梯运行了");//设置为运行状态this.setState(RUNNING_STATE);break;}}@Overridepublic void stop() {switch(this.state) {case OPENING_STATE:// 开门的电梯已经是是停止的了(正常情况下)break;case CLOSING_STATE:// 关门时才可以停止System.out.println("电梯停止了");this.setState(STOPPING_STATE);break;case RUNNING_STATE:// 运行时当然可以停止了System.out.println("电梯停止了");this.setState(STOPPING_STATE);break;case STOPPING_STATE:break;}}
}
6.1.3 客户端
package com.learning.state.before;/*** 客户端*/
public class Client {public static void main(String[] args) {// 创建电梯对象Lift lift = new Lift();// 设置当前电梯的状态lift.setState(ILift.OPENING_STATE);// 打开lift.open();lift.close();lift.run();lift.stop();}
}
6.1.4 结果截图

在这里插入图片描述

6.2 状态模式
6.2.1 抽象状态类
package com.learning.state.after;/*** 抽象状态类*/
public abstract class LiftState {// 声明环境角色类变量protected Context context;public void setContext(Context context){this.context = context;}// 电梯开启操作public abstract void open();// 电梯关闭操作public abstract void close();// 电梯运行操作public abstract void run();// 电梯停止操作public abstract void stop();
}
6.2.2 状态类
  • 1.开启状态类
package com.learning.state.after;/*** 开启状态类*/
public class OpeningState extends LiftState {// 当前状态要执行的方法@Overridepublic void open() {System.out.println("电梯开启");}@Overridepublic void close() {// 修改状态super.context.setLiftState(Context.CLOSING_STATE);// 调用当前状态中的context中的close方法super.context.close();}@Overridepublic void run() {// 什么都不做}@Overridepublic void stop() {// 什么都不做}
}
  • 2.运行状态类
package com.learning.state.after;/**
* 运行状态类
*/
public class RunningState extends LiftState {/*** 运行的时候是不能开电梯门*/@Overridepublic void open() {// 什么都不做}/*** 运行状态的电梯,门不需要再关*/@Overridepublic void close() {// 什么都不做}/*** 运行状态下要实现的方法*/@Overridepublic void run() {System.out.println("电梯正在运行");}/*** 运行状态可以停止*/@Overridepublic void stop() {super.context.setLiftState(Context.STOPPING_STATE);super.context.stop();}
}
  • 3.停止状态类
package com.learning.state.after;/*** 停止状态类*/
public class StoppingState extends LiftState {/*** 停止状态可以开门*/@Overridepublic void open() {// 状态修改super.context.setLiftState(Context.OPENING_STATE);// 动作委托为CloseState来执行,也就是委托给ClosingState子类执行这个动作super.context.getLiftState().open();}/*** 可以关门,这个动作不归我执行*/@Overridepublic void close() {// 状态修改super.context.setLiftState(Context.CLOSING_STATE);// 动作委托为CloseState来执行,也就是委托给ClosingState子类执行这个动作super.context.getLiftState().close();}/*** 停止后,可以再跑起来*/@Overridepublic void run() {// 状态修改super.context.setLiftState(Context.RUNNING_STATE);// 动作委托为CloseState来执行,也就是委托给ClosingState子类执行这个动作super.context.getLiftState().run();}/*** 停止方法执行*/@Overridepublic void stop() {System.out.println("电梯停止了");}
}
  • 4.关闭状态类
package com.learning.state.after;/*** 关闭状态类*/
public class ClosingState extends LiftState {/*** 电梯关闭状态可以再打开*/@Overridepublic void open() {super.context.setLiftState(Context.OPENING_STATE);super.context.open();}/*** 电梯关闭状态实现的动作*/@Overridepublic void close() {System.out.println("电梯门关闭");}/*** 电梯关门之后启动*/@Overridepublic void run() {super.context.setLiftState(Context.RUNNING_STATE);super.context.run();}/*** 电梯门关着,但没按楼层*/@Overridepublic void stop() {super.context.setLiftState(Context.STOPPING_STATE);super.context.stop();}
}
6.2.3 上下文类
package com.learning.state.after;public class Context {// 定义对应状态对象的常量public final static OpeningState OPENING_STATE = new OpeningState();public final static ClosingState CLOSING_STATE = new ClosingState();public final static RunningState RUNNING_STATE = new RunningState();public final static StoppingState STOPPING_STATE = new StoppingState();// 定义一个当前电梯状态变量private LiftState liftState;public LiftState getLiftState(){return liftState;}public void setLiftState(LiftState liftState){this.liftState = liftState;// 设置当前状态对象中的Context对象this.liftState.setContext(this);}public void open(){this.liftState.open();}public void close(){this.liftState.close();}public void run(){this.liftState.run();}public void stop(){this.liftState.stop();}}
6.2.4 上下文类
package com.learning.state.after;/*** 客户端类*/
public class Client {public static void main(String[] args) {// 创建环境角色对象Context context = new Context();// 设置当前电梯状态context.setLiftState(Context.CLOSING_STATE);context.open();context.close();context.run();context.stop();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/291274.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024-2028年中国二茂铁市场行情监测及未来发展前景研究报告

二茂铁市场供不应求 投资及产需规模均有增长 二茂铁又称二环戊二烯合铁,是一种具有芳香族性质的有机过渡金属化合物,化学式为Fe(C5H5)2,常温下为橙黄色粉末固体,有类似樟脑的气味。二茂铁不溶于水,易溶于苯、乙醚、汽油…

Jenkins实现CICD

Jenkins实现CICD JenkinsCI简介环境安装新建任务源码管理构建配置发送邮件配置自动化项目定时构建 JenkinsCD简介配置ssh保证其可以免登录接下来配置github的webhook正式实现自动化打包master主分支的代码将前端三剑客代码文件发送到网站服务器对应的tomcat Jenkins面试题 Jenk…

(分享)一个图片添加水印的小demo的页面,可自定义样式

有时候想给某张图片添加一个自己的水印,但是又懒的下载相应软件,用js canvas制作一个静态页面,对于单张图片添加自定义文字水印,大小 间距,角度可调。 页面如下: 选择图片,设置相应参数&#x…

KVM:尝试安装windows2008

最终目的是在lxd部署windows2008镜像 WindowsServer2008镜像: cn_windows_server_2008_r2_standard_enterprise_datacenter_and_web_with_sp1_x64_dvd_617598.iso 镜像参考链接: https://discussion.scottibyte.com/t/migrate-a-hyper-v-windows-vir…

44 el-dialog 的 appendToBody 属性, 导致 vue 响应式失效

前言 我们经常会碰到 一些 模型和视图 不同步的问题 通常意义上 主要的问题为 列表的某响应式数据更新着更新着 后面就变成非响应式对象了, 然后 就造成了 数据一直在更新, 但是 视图的渲染后面就未渲染了, 这是一个由于 模型上的问题 导致的数据的不在响应式更新 又或者 是…

.NET CORE 分布式事务(三) DTM实现Saga及高并发下的解决方案

目录(结尾附加项目代码资源地址) 引言: 1. SAGA事务模式 2. 拆分为子事务 3. 失败回滚 4. 如何做补偿 4.1 失败的分支是否需要补偿 5. 异常 6. 异常与子事务屏障 6.1 NPC的挑战 6.2 现有方案的问题 6.3 子事务屏障 6.4 原理 7. 更多高级场景 7.1 部分…

MySQL Explain 字段详解

Explain 工具介绍 Explain 一般被称为解释器,通过 Explain 工具,我们能分析我们使用的查询语句或是结构的性能瓶颈,它提供 MySQL 如何执行语句的信息。 使用语法: explain [extended|partition] select在 select 关键字前加 ex…

【大数据】Flink学习笔记

文章目录 认识FlinkDocker安装Flink基本概念Flink的特点Flink 和 Spark Streaming 对比 基本使用WordCount实现依赖 批模式代码流模式代码网络流模式代码在web UI上提交代码创建项目[^1]编写代码配置打包在Web UI上提交 Flink 架构系统架构核心概念并行度算子链(Opeartor Chain…

基于java+springboot+vue实现的电商个性化推荐系统(文末源码+Lw+ppt)23-389

摘 要 伴随着我国社会的发展,人民生活质量日益提高。于是对电商个性化推荐进行规范而严格是十分有必要的,所以许许多多的信息管理系统应运而生。此时单靠人力应对这些事务就显得有些力不从心了。所以本论文将设计一套电商个性化推荐系统,帮…

bert 适合 embedding 的模型

目录 背景 embedding 求最相似的 topk 结果查看 背景 想要求两个文本的相似度,就单纯相似度,不要语义相似度,直接使用 bert 先 embedding 然后找出相似的文本,效果都不太好,试过 bert-base-chinese,be…

pdf在浏览器上无法正常加载的问题

一、背景 觉得很有意思给大家分享一下。事情是这样的,开发给我反馈说,线上环境接口请求展示pdf异常,此时碰巧我前不久正好在ingress前加了一层nginx,恰逢此时内心五谷杂陈,思路第一时间便放在了改动项。捣鼓了好久无果…

vue中使用图片url直接下载图片

vue中使用图片url直接下载图片 // 下载图片downloadByBlob(url, name) {let image new Image()image.setAttribute(crossOrigin, anonymous)image.src urlimage.onload () > {let canvas document.createElement(canvas)canvas.width image.widthcanvas.height image…

Ubuntu20.04下PCL安装,查看,卸载等操作

Ubuntu20.04下PCL安装,查看,卸载等操作 项目来源 https://github.com/PointCloudLibrary/pclhttps://pointclouds.org/documentation/modules.htmlhttps://pcl.readthedocs.io/projects/tutorials/en/master/ 点云学习: https://github.c…

【Spring】SpringMvc项目当中,页面删除最后一条数据,页面不跳转并且数据为空。

期待您的关注 在之前学习SpringMvc的时候遇到过这样一个BUG,当我在一个页面删除该页面的最后一条数据的时候,一旦我删除成功,那么这个页面不会进行跳转,而是还停留在这个本不应该存在的页面,而且数据什么都没有。如下…

零基础教程:R语言lavaan结构方程模型(SEM)

查看原文>>>最新基于R语言lavaan结构方程模型(SEM)实践技术应用 基于R语言lavaan程序包,通过理论讲解和实际操作相结合的方式,由浅入深地系统介绍结构方程模型的建立、拟合、评估、筛选和结果展示的全过程。我们筛选大量…

ChatGPT与Discord的完美结合——团队协作的得力助手

本文将教你如何集成Discord Bot,助力团队在工作中实现更高效的沟通与协作。通过充分发挥ChatGPT的潜力,进一步提升工作效率和团队协作能力。无需编写任何代码即可完成本文所述的操作,进行个性化定制只需对参数进行微调即可。 方案介绍 如果在…

【JavaWeb】Day27.Web入门——Tomcat介绍

目录 WEB服务器-Tomcat 一.服务器概述 二.Web服务器 三.Tomcat- 基本使用 1.下载 2.安装与卸载 3.启动与关闭 4.常见问题 四.Tomcat- 入门程序 WEB服务器-Tomcat 一.服务器概述 服务器硬件:指的也是计算机,只不过服务器要比我们日常使用的计算…

AI绘画核心技术与实战【课程推荐】

AI结合绘画领域属于是《黑客与画家》的结合了,推荐大家来一起学习

Linux:程序地址空间详解

目录 一、堆、栈、环境参数所在位置 二、进程地址空间底层实现原理 ​编辑 三、什么是地址空间 四、为什么要有进程地址空间 五、细谈写实拷贝的实现及意义 在C/C学习中,都学习过如上图所示的一套存储结构,我们大致知道一般存储空间分为堆区&#…

代码随想录算法训练营三刷 day38 | 动态规划之 509. 斐波那契数 70. 爬楼梯 746. 使用最小花费爬楼梯

三刷day38 509. 斐波那契数1 确定dp数组以及下标的含义2 确定递推公式3 dp数组如何初始化4 确定遍历顺序5 举例推导dp数组 70. 爬楼梯1 确定dp数组以及下标的含义2 确定递推公式3 dp数组如何初始化4 确定遍历顺序5 举例推导dp数组 746. 使用最小花费爬楼梯1 确定dp数组以及下标…