Java设计模式 十八 状态模式 (State Pattern)
状态模式 (State Pattern)
状态模式是一种行为型设计模式,它允许对象在其内部状态改变时改变其行为。状态模式让一个对象在其状态改变时,其行为也随之改变,看起来就像是改变了对象的类。通过将状态的变化封装到不同的状态对象中,状态模式可以使对象的行为更加灵活和可扩展。
1. 状态模式的组成
状态模式通常包含以下几个角色:
- Context(上下文):上下文类维护一个当前状态的引用,它通常会委托给具体的状态类来执行相关行为。上下文类还可以动态地切换状态。
- State(状态接口):定义了状态类的共同接口,所有具体的状态类都实现这个接口。
- ConcreteState(具体状态类):每个具体的状态类实现了
State接口,并定义了在该状态下的具体行为。
2. 状态模式的工作流程
- 上下文对象持有一个当前的状态对象,并通过调用状态对象的行为来执行相应的操作。
- 每个状态类(
ConcreteState)实现了State接口,并提供了在该状态下的具体实现。 - 上下文可以在不同状态之间进行切换,通常由外部环境或条件触发。
3. 状态模式的实现
场景示例:电梯系统
我们来实现一个简单的电梯系统。电梯可以处于多个状态,比如:空闲、运行、停靠。每个状态下电梯的行为不同。通过状态模式,我们可以根据电梯的不同状态执行不同的行为。
1) 定义状态接口
状态接口定义了电梯所支持的操作,如openDoor()、closeDoor()等。
// 状态接口
public interface ElevatorState {void openDoor();void closeDoor();void moveUp();void moveDown();
}
2) 定义具体状态类
每个具体的状态类实现了ElevatorState接口,并定义了该状态下电梯的具体行为。
// 空闲状态
public class IdleState implements ElevatorState {private Elevator elevator;public IdleState(Elevator elevator) {this.elevator = elevator;}@Overridepublic void openDoor() {System.out.println("The door is opening.");elevator.setCurrentState(elevator.getOpenState());}@Overridepublic void closeDoor() {System.out.println("The door is already closed.");}@Overridepublic void moveUp() {System.out.println("The elevator is moving up.");elevator.setCurrentState(elevator.getMovingUpState());}@Overridepublic void moveDown() {System.out.println("The elevator is moving down.");elevator.setCurrentState(elevator.getMovingDownState());}
}// 开门状态
public class OpenState implements ElevatorState {private Elevator elevator;public OpenState(Elevator elevator) {this.elevator = elevator;}@Overridepublic void openDoor() {System.out.println("The door is already open.");}@Overridepublic void closeDoor() {System.out.println("Closing the door.");elevator.setCurrentState(elevator.getIdleState());}@Overridepublic void moveUp() {System.out.println("Cannot move while the door is open.");}@Overridepublic void moveDown() {System.out.println("Cannot move while the door is open.");}
}// 上升状态
public class MovingUpState implements ElevatorState {private Elevator elevator;public MovingUpState(Elevator elevator) {this.elevator = elevator;}@Overridepublic void openDoor() {System.out.println("Cannot open the door while the elevator is moving up.");}@Overridepublic void closeDoor() {System.out.println("The door is already closed.");}@Overridepublic void moveUp() {System.out.println("The elevator is already moving up.");}@Overridepublic void moveDown() {System.out.println("Changing direction to move down.");elevator.setCurrentState(elevator.getMovingDownState());}
}// 下降状态
public class MovingDownState implements ElevatorState {private Elevator elevator;public MovingDownState(Elevator elevator) {this.elevator = elevator;}@Overridepublic void openDoor() {System.out.println("Cannot open the door while the elevator is moving down.");}@Overridepublic void closeDoor() {System.out.println("The door is already closed.");}@Overridepublic void moveUp() {System.out.println("Changing direction to move up.");elevator.setCurrentState(elevator.getMovingUpState());}@Overridepublic void moveDown() {System.out.println("The elevator is already moving down.");}
}
3) 定义上下文类
Elevator类是上下文类,负责维护当前的状态,并委托给具体状态类执行操作。
// 电梯类(上下文)
public class Elevator {private ElevatorState idleState;private ElevatorState openState;private ElevatorState movingUpState;private ElevatorState movingDownState;private ElevatorState currentState;public Elevator() {idleState = new IdleState(this);openState = new OpenState(this);movingUpState = new MovingUpState(this);movingDownState = new MovingDownState(this);currentState = idleState; // 默认初始状态为空闲状态}// 切换状态public void setCurrentState(ElevatorState state) {this.currentState = state;}// 获取当前状态public ElevatorState getCurrentState() {return currentState;}public ElevatorState getIdleState() {return idleState;}public ElevatorState getOpenState() {return openState;}public ElevatorState getMovingUpState() {return movingUpState;}public ElevatorState getMovingDownState() {return movingDownState;}// 电梯操作public void openDoor() {currentState.openDoor();}public void closeDoor() {currentState.closeDoor();}public void moveUp() {currentState.moveUp();}public void moveDown() {currentState.moveDown();}
}
4) 客户端代码
客户端代码模拟了电梯的操作,演示了不同状态下电梯的行为。
public class Client {public static void main(String[] args) {// 创建电梯对象Elevator elevator = new Elevator();// 电梯空闲时elevator.openDoor(); // 输出:The door is opening.elevator.moveUp(); // 输出:The elevator is moving up.// 电梯上升时elevator.moveDown(); // 输出:Changing direction to move down.elevator.openDoor(); // 输出:Cannot open the door while the elevator is moving down.// 电梯下降时elevator.closeDoor(); // 输出:The door is already closed.elevator.moveUp(); // 输出:Changing direction to move up.}
}
运行结果:
The door is opening.
The elevator is moving up.
Changing direction to move down.
Cannot open the door while the elevator is moving down.
The door is already closed.
Changing direction to move up.
4. 状态模式的优点
- 封装状态行为: 每个状态类封装了具体的状态行为,使得不同状态的行为不会混合在一起。
- 扩展性: 当需要添加新的状态时,可以通过增加新的状态类而不影响现有的代码,符合开闭原则。
- 清晰的状态转换: 状态的转换和每个状态的行为都清晰地定义在具体状态类中,使得代码更容易理解和维护。
5. 状态模式的缺点
- 类的数量增加: 每个状态都需要定义一个具体的状态类,当状态种类较多时,可能会导致类的数量激增,增加系统复杂度。
- 状态之间的相互依赖: 有时状态之间的转换逻辑较为复杂,可能会引发状态类之间的依赖关系,需要小心设计。
6. 状态模式的应用场景
- 工作流引擎: 当某个任务根据不同的状态执行不同操作时,状态模式非常适用,例如审批流程中的不同状态(待审批、审批中、已通过、已拒绝等)。
- 有限状态机: 适用于有限的状态集合,如游戏中的玩家状态(例如,待机、攻击、跳跃等)。
- GUI组件: 例如,按钮、窗体等可以有不同的状态(激活、禁用、隐藏等),这些状态的行为可以通过状态模式来管理。
7. 总结
状态模式通过将每个状态的行为封装在独立的状态对象中,使得对象的行为随状态变化而变化。这种模式可以有效地管理和扩展具有多个状态的对象,特别是在复杂的状态转移和行为执行场景中,它提供了一种灵活且清晰的解决方案。
相关文章:
Java设计模式 十八 状态模式 (State Pattern)
状态模式 (State Pattern) 状态模式是一种行为型设计模式,它允许对象在其内部状态改变时改变其行为。状态模式让一个对象在其状态改变时,其行为也随之改变,看起来就像是改变了对象的类。通过将状态的变化封装到不同的状态对象中,…...
PyTorch张量操作reshape view permute transpose
1. reshape() 和 view() view和reshape都用于改变张量的shape view是reshape的一个特例,view要求张量在内存中是连续的,否则会抛出错误,view只能用于contiguous的张量 reshape会自动处理contiguous的情况,如果张量是contiguous…...
RabbitMQ5-死信队列
目录 死信的概念 死信的来源 死信实战 死信之TTl 死信之最大长度 死信之消息被拒 死信的概念 死信,顾名思义就是无法被消费的消息,一般来说,producer 将消息投递到 broker 或直接到queue 里了,consumer 从 queue 取出消息进…...
macOS使用LLVM官方发布的tar.xz来安装Clang编译器
之前笔者写过一篇博文ubuntu使用LLVM官方发布的tar.xz来安装Clang编译器介绍了Ubuntu下使用官方发布的tar.xz包来安装Clang编译。官方发布的版本中也有MacOS版本的tar.xz,那MacOS应该也是可以安装的。 笔者2015款MBP笔记本,CPU是intel的,出厂…...
【算法学习】归并排序算法思想的应用—求逆序对数量
Hey,大家好!👋 今天我们来聊聊一个有趣的话题——如何在归并排序的基础上,高效解决求逆序对数量的问题。如果你对算法感兴趣,或者正在准备算法面试,这篇文章一定会对你有所帮助!🚀 …...
一组开源、免费、Metro风格的 WPF UI 控件库
前言 今天大姚给大家分享一个开源、免费、Metro风格的 WPF UI 控件库:MahApps.Metro。 项目介绍 MahApps.Metro 是一个开源、免费、Metro风格的 WPF UI 控件库,提供了现代化、平滑和美观的控件和样式,帮助开发人员轻松创建具有现代感的 Win…...
Spring Security 应用详解
Spring Security 应用详解 集成SpringBootSpring Boot 介绍创建maven工程spring 容器配置Servlet Context配置安全配置测试 工作原理结构总览认证流程认证流程AuthenticationProviderUserDetailsServicePasswordEncoder 授权流程授权流程授权决策 自定义认证自定义登录页面认证…...
业务对象和对象的区别
"业务对象"和"对象"这两个术语在日常编程和软件工程中经常被使用,但它们之间存在一些区别,主要体现在它们的目的、范围和抽象层次上。 ### 对象(Object) 1. **定义**: - 对象是面向对象编程&#…...
81,【5】BUUCTF WEB [b01lers2020]Life on Mars
进入靶场 怎莫颠颠的,一下子就想到展博了 先把左边的挨个点一遍 在最后一个有点收获 不过也没其他收获了 这种进去给个正常网页的题目,基本都靠url获取信息了 抓包看看有没有其他信息 竟然没有任何信息 自闭了 看别人的wp去咯 为什么别人抓到的包里…...
华硕笔记本装win10哪个版本好用分析_华硕笔记本装win10专业版图文教程
华硕笔记本装win10哪个版本好用?华硕笔记本还是建议安装win10专业版。Win分为多个版本,其中家庭版(Home)和专业版(Pro)是用户选择最多的两个版本。win10专业版在功能以及安全性方面有着明显的优势ÿ…...
Linux进程 -fork(初识),进程状态和进程优先级
目录 一、通过系统调用创建进程-fork 1.fork的介绍 2.fork的理解 3.fork常规用法 4.fork的三个问题 5.创建多个子进程 二、进程状态 (1)Linux内核源代码 (2)进程的状态 R运行状态(运行态) S 睡眠状态&…...
数据从前端传到后端入库过程分析
数据从前端传到后端入库过程分析 概述 积累了一些项目经验,成长为一个老程序员了,自认为对各种业务和技术都能得心应手的应对了,殊不知很多时候我们借助了搜索引擎的能力,当然现在大家都是通过AI来武装自己。 今天要分析的话题是…...
macOS如何进入 Application Support 目录(cd: string not in pwd: Application)
错误信息 cd: string not in pwd: Application 表示在当前目录下找不到名为 Application Support 的目录。可能的原因如下: 拼写错误或路径错误:确保你输入的目录名称正确。目录名称是区分大小写的,因此请确保使用正确的大小写。正确的目录名…...
第38周:猫狗识别 (Tensorflow实战第八周)
目录 前言 一、前期工作 1.1 设置GPU 1.2 导入数据 输出 二、数据预处理 2.1 加载数据 2.2 再次检查数据 2.3 配置数据集 2.4 可视化数据 三、构建VGG-16网络 3.1 VGG-16网络介绍 3.2 搭建VGG-16模型 四、编译 五、训练模型 六、模型评估 七、预测 总结 前言…...
【2024年华为OD机试】 (A卷,200分)- 计算网络信号、信号强度(JavaScriptJava PythonC/C++)
一、问题描述 题目解析 问题描述 我们有一个 m x n 的二维网格地图,每个格子可能是以下几种情况之一: 0:表示该位置是空旷的。x(正整数):表示该位置是信号源,信号强度为 x。-1:表示该位置是阻隔物,信号无法直接穿透。信号源只有一个,阻隔物可能有多个。信号在传播…...
【go语言】数组和切片
一、数组 1.1 什么是数组 数组是一组数:数组需要是相同类型的数据的集合;数组是需要定义大小的;数组一旦定义了大小是不可以改变的。 1.2 数组的声明 数组和其他变量定义没有什么区别,唯一的就是这个是一组数,需要给…...
2025美赛MCM数学建模A题:《石头台阶的“记忆”:如何用数学揭开历史的足迹》(全网最全思路+模型)
✨个人主页欢迎您的访问 ✨期待您的三连 ✨ 《石头台阶的“记忆”:如何用数学揭开历史的足迹》 目录 《石头台阶的“记忆”:如何用数学揭开历史的足迹》 ✨摘要✨ ✨引言✨ 1. 引言的结构 2. 撰写步骤 (1)研究背景 &#…...
使用 Docker Compose 一键启动 Redis、MySQL 和 RabbitMQ
目录 一、Docker Compose 简介 二、服务配置详解 1. Redis 配置 2. MySQL 配置 3. RabbitMQ 配置 三、数据持久化与时间同步 四、部署与管理 五、总结 目录挂载与卷映射的区别 现代软件开发中,微服务架构因其灵活性和可扩展性而备受青睐。为了支持微服务的…...
新增自定义数据功能|UWA Gears V1.0.7
UWA Gears 是UWA最新发布的无SDK性能分析工具。针对移动平台,提供了实时监测和截帧分析功能,帮助您精准定位性能热点,提升应用的整体表现。 本次版本更新新增了自定义数据功能,支持灵活定义和捕获关键性能指标,满足特…...
docker 简要笔记
文章目录 一、前提内容1、docker 环境准备2、docker-compose 环境准备3、流程说明 二、打包 docker 镜像1、基础镜像2、国内镜像源3、基础的dockerfile4、打包镜像 四、构建运行1、docker 部分2、docker-compose 部分2.1、构建docker-compose.yml2.1.1、同目录构建2.1.2、利用镜…...
linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...
GraphQL 实战篇:Apollo Client 配置与缓存
GraphQL 实战篇:Apollo Client 配置与缓存 上一篇:GraphQL 入门篇:基础查询语法 依旧和上一篇的笔记一样,主实操,没啥过多的细节讲解,代码具体在: https://github.com/GoldenaArcher/graphql…...
