【Java 设计模式】行为型之状态模式

文章目录

    • 1. 定义
    • 2. 应用场景
    • 3. 代码实现
    • 结语

状态模式(State Pattern)是一种行为型设计模式,用于通过将对象的行为封装到不同的状态类中,使得对象在不同的状态下具有不同的行为。状态模式允许对象在内部状态发生改变时改变其行为,而无需修改其代码。在本文中,我们将深入研究Java中状态模式的定义、结构、使用场景以及如何在实际开发中应用。

1. 定义

状态模式是一种行为型设计模式,用于通过将对象的行为封装到不同的状态类中,使得对象在不同的状态下具有不同的行为。状态模式允许对象在内部状态发生改变时改变其行为,而无需修改其代码。状态模式通常包含三个主要角色:上下文(Context)、抽象状态(Abstract State)和具体状态(Concrete State)。

  • 上下文(Context): 定义了一个接口,用于维护一个当前状态的引用,并提供一个用于切换状态的方法
  • 抽象状态(Abstract State): 定义了一个接口,用于封装与上下文相关的一个或多个行为
  • 具体状态(Concrete State): 实现了抽象状态的接口,负责处理与状态相关的行为

2. 应用场景

状态模式通常在以下场景中使用:

  • 一个对象的行为取决于其内部状态,并且需要在运行时根据内部状态改变其行为:

    当一个对象的行为取决于其内部状态,并且需要在运行时根据内部状态改变其行为时,可以使用状态模式

  • 一个对象具有多个状态,并且状态之间存在转换关系:

    当一个对象具有多个状态,并且这些状态之间存在转换关系时,可以使用状态模式

  • 避免使用过多的条件语句来控制对象的行为:

    当需要避免使用过多的条件语句来控制对象的行为时,可以使用状态模式,将每个状态封装到一个类中,使得代码更加清晰和可维护

3. 代码实现

下面通过一个简单的例子来演示状态模式的实现。假设有一个电梯系统,电梯有开门、关门、上行、下行和停止等状态,我们可以使用状态模式来管理电梯的不同状态。

上下文 - 电梯 ElevatorContext

package com.cheney.demo;class ElevatorContext {private ElevatorState currentState;public ElevatorContext() {this.currentState = new StoppedState();}public void setState(ElevatorState state) {this.currentState = state;}public void openDoor() {currentState.openDoor(this);}public void closeDoor() {currentState.closeDoor(this);}public void moveUp() {currentState.moveUp(this);}public void moveDown() {currentState.moveDown(this);}
}

抽象状态 - 电梯状态 ElevatorState

package com.cheney.demo;interface ElevatorState {void openDoor(ElevatorContext context);void closeDoor(ElevatorContext context);void moveUp(ElevatorContext context);void moveDown(ElevatorContext context);
}

具体状态 - 停止状态 StoppedState

package com.cheney.demo;class StoppedState implements ElevatorState {@Overridepublic void openDoor(ElevatorContext context) {System.out.println("开门");context.setState(new OpenedState());}@Overridepublic void closeDoor(ElevatorContext context) {System.out.println("门已经关上了");}@Overridepublic void moveUp(ElevatorContext context) {System.out.println("向上移动");context.setState(new MovingUpState());}@Overridepublic void moveDown(ElevatorContext context) {System.out.println("向下移动");context.setState(new MovingDownState());}
}

具体状态 - 开门状态 OpenedState

package com.cheney.demo;class OpenedState implements ElevatorState {@Overridepublic void openDoor(ElevatorContext context) {System.out.println("门已经打开了");}@Overridepublic void closeDoor(ElevatorContext context) {System.out.println("关上门");context.setState(new StoppedState());}@Overridepublic void moveUp(ElevatorContext context) {System.out.println("门打开时无法向上移动");}@Overridepublic void moveDown(ElevatorContext context) {System.out.println("门打开时无法向下移动");}
}

具体状态 - 上行状态 MovingUpState

package com.cheney.demo;class MovingUpState implements ElevatorState {@Overridepublic void openDoor(ElevatorContext context) {System.out.println("向上移动时无法打开门");}@Overridepublic void closeDoor(ElevatorContext context) {System.out.println("关上门");context.setState(new StoppedState());}@Overridepublic void moveUp(ElevatorContext context) {System.out.println("继续向上移动");}@Overridepublic void moveDown(ElevatorContext context) {System.out.println("改变方向向下移动");context.setState(new MovingDownState());}
}

具体状态 - 下行状态 MovingDownState

package com.cheney.demo;class MovingDownState implements ElevatorState {@Overridepublic void openDoor(ElevatorContext context) {System.out.println("向下移动时无法打开门");}@Overridepublic void closeDoor(ElevatorContext context) {System.out.println("关上门");context.setState(new StoppedState());}@Overridepublic void moveUp(ElevatorContext context) {System.out.println("改变方向向上移动");context.setState(new MovingUpState());}@Overridepublic void moveDown(ElevatorContext context) {System.out.println("继续向下移动。");}
}

客户端启动类 Main

package com.cheney.demo;public class Main {public static void main(String[] args) {// 使用状态模式管理电梯状态ElevatorContext elevator = new ElevatorContext();// 打开门elevator.openDoor();// 关上门elevator.closeDoor();// 向上移动elevator.moveUp();// 改变方向向下移动elevator.moveDown();// 向下移动时无法打开门elevator.openDoor();}
}

在上述例子中,ElevatorContext 是上下文类,维护了当前状态的引用,并提供了用于切换状态的方法。ElevatorState 是抽象状态接口,定义了与电梯状态相关的行为。StoppedStateOpenedStateMovingUpStateMovingDownState 是具体状态类,分别实现了抽象状态接口,负责处理不同状态下的行为。

在客户端中,我们使用状态模式管理电梯的状态。通过将电梯的不同状态封装到不同的状态类中,实现了电梯状态的切换,而无需修改 ElevatorContext 的代码。

结语

状态模式是一种用于通过将对象的行为封装到不同的状态类中,使得对象在不同的状态下具有不同的行为的设计模式。通过使用状态模式,可以使代码更加清晰、可维护,并降低对象之间的耦合度。在实际开发中,状态模式常被用于处理对象的状态转换、状态机等场景。通过合理使用状态模式,可以提高系统的可扩展性和灵活性。

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

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

相关文章

【极数系列】Flink项目入门搭建(03)

【极数系列】Flink项目入门搭建(03) 引言 gitee地址:https://gitee.com/shawsongyue/aurora.git 源码直接下载可运行,模块:aurora_flink Flink 版本:1.18.0 Jdk 版本:11 1.创建mavenx项目 2.…

清越 peropure·AI 国内版ChatGP新功能介绍

当OpenAI发布ChatGPT的时候,没有人会意识到,新一代人工智能浪潮将给人类社会带来一场眩晕式变革。其中以ChatGPT为代表的AIGC技术加速成为AI领域的热门发展方向,推动着AI时代的前行发展。面对技术浪潮,清越科技(PeroPure)立足多样化生活场景、精准把握用户实际需求,持续精确Fin…

SpringBoot+Vue充电桩管理系统 附带详细运行指导视频

文章目录 一、项目演示二、项目介绍三、运行截图四、主要代码1. 分页获取预约数据代码2.保存预约信息代码3.修改订单状态代码 一、项目演示 项目演示地址: 视频地址 二、项目介绍 项目描述:这是一个基于SpringBootVue框架开发的充电桩管理系统。首先&…

【报错解决】anaconda: Read timed out.

报错描述 在anaconda的虚拟环境中用pip或conda下载安装包时,遇到如下报错,具体报错内容如下所示: raise ReadTimeoutError(self._pool, None, "Read timed out.") pip._vendor.urllib3.exceptions.ReadTimeoutError: HTTPSConnect…

网络安全的使命:守护数字世界的稳定和信任

在数字化时代,网络安全的角色不仅仅是技术系统的守护者,更是数字社会的信任保卫者。网络安全的使命是保护、维护和巩固数字世界的稳定性、可靠性以及人们对互联网的信任。本文将深入探讨网络安全是如何履行这一使命的。 第一部分:信息资产的…

怎么给wordpress网站底部页脚添加备案号和链接?

以前“WordPress后台 >> 常规”最底部是有一个ICP备案号的,我们只需要填写备案号并保存更改即可让WordPress自带主题底部显示ICP备案号,但是现在新版本的WordPress已经没有了这个ICP备案号选项,而且也无法直接添加公安联网备案号&#…

vscode debug

需要对GitHub上的工程debug。 所以花时间看了下,参考了bili视频和chatgpt的解答。 chatgpt给的步骤 要在 VS Code 中调试 C++ 项目,可以按照以下步骤进行设置和操作: 确保已安装 C++ 扩展:在 VS Code 中选择 “Extensions”(或使用快捷键 Ctrl+Shift+X),搜索并安装官…

Typecho后台无法登录显示503 service unavailable问题及处理

一、Typecho 我的博客地址:https://www.aomanhao.top 使用老薛主机动态Typecho博客框架handsome主题的搭配,文章内容可以异地网页更新,可以听后台背景音乐,很好的满足我的痛点需求,博客部署在云端服务器访问响应较快…

mac intel jdk安装与配置

jdk地址下载 https://www.oracle.com/java/technologies/downloads/ https://repo.huaweicloud.com/java/jdk/8u201-b09/ 安装后 下载完成之后打开终端 注意如果是第一次配置环境变量需要创建.bash_profile文件。(注意:touch后面有空格) to…

dpkt库多次循环读取PCAP文件中的完整数据方法

dpkt库多次循环读取PCAP文件中的完整数据方法 1. 问题 使用下面方法,结果发现第一次for循环和第二次for循环进去time_stamp不一样,而我需要两次都读取完整数据,所以就需要找方法解决一下这个问题。 fp = open(22.pcapng, rb) pcap = dpkt.pcapng.Reader(fp)for ts, buf i…

单调栈笔记

单调栈 1.每日温度2.下一个更大元素 I3.下一个更大的元素4.接雨水5.柱状图中最大的矩形 单调栈正如其名字,用一个栈(能够实现栈性质的数据结构就行)来存储元素,存储在栈中的元素保持单调性(单调递增或者是单调递减&…

信息检索与数据挖掘 | (十)线性回归与逻辑回归

文章目录 📚线性回归算法流程📚Bias and variance📚过拟合&欠拟合📚逻辑回归算法流程 📚线性回归算法流程 ybwx 使用loss function L来评估函数的好坏 从而我们要选择使L最小的模型参数w,b 使用梯度下降的方法…

所有博客导航--总结

一、Java相关知识点 1.Java 2实用教程-输入输出数据 2.Java 2实用教程-类型转换运算 3.Java 2实用教程-基本数据类型 4.Java 2 实用教程-标识符与关键字 5.java 2 实用教程-数组 1.基本数据类型与数组第一节 2.基本数据类型与数组第二节 6.Java 2实用教程-运算符与表达…

JAVA 学习 面试(六)数据类型与方法

数据类型 基本数据类型 为什么float3.4报错 3.4 默认是浮点double类型的,如果赋值给float是向下转型,会出现精度缺失,,需要强制转换 Switch支持的数据类型? byte、short、int、char 、 enum 、 String 基本类型与包…

openssl加解密和签名验签步骤操作记录

文章目录 一、AES加解密操作1.1 EBC模式1.2 CBC模式 二、RSA加解密操作三、RSA 加解密和 AES 加解密对比四、RSA签名和验签操作 一、AES加解密操作 1.1 EBC模式 使用 OpenSSL 进行 AES 的 ECB(电子密码本)模式加解密相对简单。以下是基本步骤&#xff…

trino-435: trino接入TIDB数据源

文章目录 一、TIDB介绍二、TIDB源接入流程三、遇到的错误1、数据源注册:2、查询表数据一、TIDB介绍 二、TIDB源接入流程 三、遇到的错误 1、数据源注册: http://localhost:8080/v1/catalog/register?name=tidb_test {"connector.name":"tidb",&quo…

SpringBoot整合QQ邮箱发送验证码

一、QQ开启SMTP 打开QQ邮箱&#xff0c;点击设置&#xff0c;进入账号&#xff0c;往下滑后&#xff0c;看见服务状态后&#xff0c;点击管理服务 进入管理服务后&#xff0c;打开服务&#xff0c;然后获取授权码 二 、导入依赖 <!-- 邮箱--><dependency>&…

php低版本(7.4)配置过程中遇到的问题及基本解决手段

目前php不支持较低版本的安装&#xff0c;如果安装低版本必须借助第三方库shivammathur //将第三方仓库加入brewbrew tap shivammathur/php //安装PHPbrew install shivammathur/php/php7.4 可能出现的问题 像这样突然中止然后报错&#xff0c;一般是网络问题&#xff0c;或…

Random Sprays Retinex 传统的图像增强算法RSR

文章目录 前言1、Random Sprays Retinex 概况2、Random Sprays Retinex 具体实现2.1、喷雾的生成2.2、径向密度函数的确定2.3、像素的选择2.4、亮度的计算2.5、参数的调整 3、Random Sprays Retinex 算法效果的表现4、Random Sprays Retinex 现存的问题 前言 Random Spray Reti…

C++面试宝典第24题:袋鼠过河

题目 一只袋鼠要从河这边跳到河对岸,河很宽,但是河中间打了很多桩子。每隔一米就有一个桩子,每个桩子上都有一个弹簧,袋鼠跳到弹簧上就可以跳得更远。每个弹簧力量不同,用一个数字代表它的力量,如果弹簧力量为5,就代表袋鼠下一跳最多能够跳5米;如果为0,就会陷进去无法…