详解状态模式
引言
水有固态、液态、气态三种状态,在不同条件下这三种状态可以相互转化。同样在软件设计中,有些对象也有不同的状态,不同状态的行为不同,状态模式就是用来处理这种情况的。
1.概念
状态模式(State Pattern):允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Objects for States),状态模式是一种对象行为型模式。
2.模式结构
3.模式分析
Context:环境类,又称为上下文类,它是拥有多种状态的对象。由于环境类的状态存在多样性且在不同状态下对象的行为有所不同,因此将状态独立出去形成单独的状态类。在环境类中维护一个抽象状态类State的实例,这个实例定义当前状态,在具体实现时它是一个State子类的对象。核心代码如下:
class Context {private State state;//维持一个对抽象状态对象的引用private int value;//其他属性值,该属性值的变化可能会导致对象状态发生变化//设置状态对象public void setState(State state) {this.state = state;}public void request() {//其他代码state.handle();//调用状态对象的业务方法//其他代码}}
State:抽象状态类,它用于定义一个接口以封装与环境类的一个特定状态相关的行为,在抽象状态类中声明了各种不同状态对应的方法,而在其子类中实现类这些方法,由于不同状态下对象的行为可能不同,因此在不同子类中方法的实现可能存在不同,相同的方法可以写在抽象状态类中。核心代码如下:
public abstract class State {//声明抽象业务方法,不同的具体状态类可以不同的实现public abstract void handle();}
ConcreteState:具体状态类,它是抽象状态类的子类,每一个子类实现一个与环境类的一个状态相关的行为,每一个具体状态类对应环境的一个具体状态,不同的具体状态类其行为有所不同。核心代码如下:
class ConcreteState extends State {public void handle() {//方法具体实现代码}}
有关状态之间的相互转化,可以有两种方式:1.由环境类负责,根据环境类的属性value的值来控制状态的转化。2.由具体状态类负责,将环境类作为参数传入具体状态类的方法中,根据环境类的属性value的值来控制状态的转化。
4.具体实例分析
为了简化理解,没有使用value属性,而是选择方式1定义方法进行状态转。
ElevatorState:抽象状态类,是接口,表示电梯的状态,其中电梯有开门和关门两种状态,开门状态下电梯只能停止,关门状态下电梯才可以移动。具体代码如下:
//电梯状态public interface ElevatorState {void openDoor();void closeDoor();void move();void stop();}
OpenState:电梯的开门状态,实现抽象状态类接口,模拟开门状态的行为:停止,并且开门状态可以向关门状态转化(在环境类实现)。具体代码如下:
// 具体状态类:开门状态class OpenState implements ElevatorState {@Overridepublic void openDoor() {System.out.println("当前状态:开门状态,电梯已经开门");}@Overridepublic void closeDoor() {System.out.println("当前状态:开门状态,电梯要关门了");}@Overridepublic void move() {System.out.println("当前状态:开门状态,开门状态下不能移动");}@Overridepublic void stop() {System.out.println("当前状态:开门状态,开门状态下电梯已经停止");}}
CloseState:电梯的关门状态,实现抽象状态类接口,模拟关门状态的行为:电梯移动,并且关门状态可以向开门状态转化(在环境类实现)。具体代码如下:
// 具体状态类:关门状态class CloseState implements ElevatorState {@Overridepublic void openDoor() {System.out.println("当前状态:关门状态,电梯要开门了");}@Overridepublic void closeDoor() {System.out.println("当前状态:关门状态,电梯已经关门");}@Overridepublic void move() {System.out.println("当前状态:关门状态,电梯正在移动");}@Overridepublic void stop() {System.out.println("当前状态:关门状态,电梯要停止了");}}
ElevatorContext:环境类,控制电梯状态的转化,内部维持了电梯的状态的引用,便于记录此时电梯的状态。具体代码如下:
class ElevatorContext {private ElevatorState elevatorState;//维持一个对抽象状态对象的引用public ElevatorContext() {elevatorState = new CloseState(); // 初始状态为关门状态}public void setState(ElevatorState state) {this.elevatorState = state;}public void openDoor() {elevatorState = new OpenState();elevatorState.openDoor();}public void closeDoor() {elevatorState = new CloseState();elevatorState.closeDoor();}public void move() {elevatorState.move();}public void stop() {elevatorState.stop();}}
Client:客户端,模拟电梯从开门上人到运送到楼层后开门放人的过程。具体代码如下:
public class Client {public static void main(String[] args) {ElevatorContext elevator = new ElevatorContext();elevator.openDoor();elevator.move();elevator.closeDoor();elevator.move();elevator.stop();elevator.openDoor();}}
运行代码,结果如下:
5.优缺点
主要优点如下:
(1)封装了状态的转换规则,在状态模式中可以将状态的转换代码封装在环境类或者具体状态类中,可以对状态转换代码进行集中管理,而不是分散在一个个业务方法中。
(2)将所有与某个状态有关的行为放到一个类中,只需要注入一个不同的状态对象即可使环境对象拥有不同的行为。
(3)允许状态转换逻辑与状态对象合成一体,而不是提供一个巨大的条件语句块,状态模式可以让我们避免使用庞大的条件语句来将业务方法和状态转换代码交织在一起。
(4)可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
主要缺点如下:
(1)状态模式的使用必然会增加系统中类和对象的个数,导致系统运行开销增大。
(2)状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱,增加系统设计的难度。
(3)状态模式对“开闭原则”的支持并不太好,增加新的状态类需要修改那些负责状态转换的源代码,否则无法转换到新增状态。而且修改某个状态类的行为也需修改对应类的源代码。
6.适用情况
(1)对象的行为依赖于它的状态(如某些属性值),状态的改变将导致行为的变化。
(2)在代码中包含大量与对象状态有关的条件语句,这些条件语句的出现,会导致代码的可维护性和灵活性变差,不能方便地增加和删除状态,并且导致客户类与类库之间的耦合增强。
相关文章:

详解状态模式
引言 水有固态、液态、气态三种状态,在不同条件下这三种状态可以相互转化。同样在软件设计中,有些对象也有不同的状态,不同状态的行为不同,状态模式就是用来处理这种情况的。 1.概念 状态模式(State Pattern):允许一个…...
能否通过蓝牙建立TCP/IP连接来传输数据
前言: 最近在做一个项目时,产生了一个疑问:能否通过蓝牙建立TCP/IP连接来传输数据 查阅了一些文章,可以得出结论:不行 下面是我截取的两篇个人认可的文章的回答: 文章一: 蓝牙是一种短距离无…...
uniapp mqttjs 小程序开发
在UniApp中集成MQTT.js开发微信小程序时,需注意平台差异、协议兼容性及消息处理等问题。以下是关键步骤与注意事项的综合指南: 一、环境配置与依赖安装 安装MQTT.js 推荐使用兼容性较好的版本:mqtt4.1.0(H5和小程序兼容性最佳&…...

爬虫工程师分享:获取京东商品详情SKU数据的技术难点与攻破方法
在电商数据领域,京东商品详情页的SKU数据是许多爬虫工程师的目标。这些数据包含了商品的价格、库存、规格等关键信息,对于市场分析、价格监控等应用场景至关重要。然而,获取这些数据并非易事,京东作为国内电商巨头,其反…...

数据库操作与数据管理——Rust 与 SQLite 的集成
第六章:数据库操作与数据管理 第一节:Rust 与 SQLite 的集成 在本节中,我们将深入探讨如何在 Rust 中使用 SQLite 数据库,涵盖从基本的 CRUD 操作到事务处理、数据模型的构建、性能优化以及安全性考虑等方面。SQLite 是一个轻量…...

LeetCode 0063.不同路径 II:动态规划 - 原地使用地图数组,几乎无额外空间开销
【LetMeFly】63.不同路径 II:动态规划 - 原地使用地图数组,几乎无额外空间开销 力扣题目链接:https://leetcode.cn/problems/unique-paths-ii/ 给定一个 m x n 的整数数组 grid。一个机器人初始位于 左上角(即 grid[0][0]&#…...

elementui:el-table支持搜索、切换分页多选功能,以及数据回显
1、el-table相关代码,需注意:row-key"(row) > { return row.id }" 以及 :reserve-selection"true" <div class"boxList"><div class"search-form"><!-- 搜索表单 --><el-form :inline"true&q…...
深度整理总结MySQL——索引正确使用姿势
索引正确使用姿势 前言MySQL索引优缺点分析✅ 索引的优势⚠️ 索引的代价 如何合理建立索引?——关键原则总结重要的优化机制索引覆盖——通俗的方式讲解索引下推索引跳跃式扫描 前言 这篇文章是补充一些基本概念和实战的一些使用建议. MySQL索引优缺点分析 ✅ 索引的优势 …...

使用LLaMA Factory踩坑记录
前置条件:电脑显卡RTX 4080 问题:LLaMA-Factory在运行的时候,弹出未检测到CUDA的报错信息 结论:出现了以上的报错,主要可以归结于以下两个方面: 1、没有安装GPU版本的pytorch,下载的是CPU版本…...

亚博microros小车-原生ubuntu支持系列:25 二维码控制运动
二维码识别 安装依赖 pip3 install pyzbarsudo apt install libzbar-dev 在用小车识别之前,先用电脑的摄像头测试下基本的识别 import cv2 import rclpy from rclpy.node import Node import pyzbar.pyzbar as pyzbar import numpy as np from ament_index_pyth…...
基于深度学习的人工智能量化衰老模型构建与全流程应用研究
一、引言 1.1 研究背景与意义 1.1.1 人口老龄化现状与挑战 人口老龄化是当今全球面临的重要社会趋势之一,其发展态势迅猛且影响深远。根据联合国的相关数据,1980 年,全球 65 岁及以上人口数量仅为 2.6 亿,到 2021 年,这一数字已翻番,达到 7.61 亿,而预计到 2050 年,…...

【医院运营统计专题】2.运营统计:医院管理的“智慧大脑”
医院成本核算、绩效管理、运营统计、内部控制、管理会计专题索引 引言 在当今医疗行业快速发展的背景下,医院运营管理的科学性和有效性成为了决定医院竞争力和可持续发展能力的关键因素。运营统计作为医院管理的重要工具,通过对医院各类数据的收集、整理、分析和解读,为医…...

Spring Boot Actuator使用
说明:本文介绍Spring Boot Actuator的使用,关于Spring Boot Actuator介绍,下面这篇博客写得很好,珠玉在前,我就不多介绍了。 Spring Boot Actuator 简单使用 项目里引入下面这个依赖 <!--Spring Boot Actuator依…...
【AI应用】免费的文本转语音工具:微软 Edge TTS 和 开源版 ChatTTS 对比
【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】【读书与思考】【AI应用】 我试用了下Edge TTS,感觉还不错,不过它不支持克隆声音(比如自己的声音) 微软 Edge TTS 和 开源版 ChatTTS 都是免费的 文本转语音&…...

如何在 Qt 中添加和使用系统托盘图标
在 Qt 中实现系统托盘图标是一个常见的需求,尤其是在桌面应用程序中。系统托盘图标可以让应用程序在后台运行时仍然具有可见性,同时避免占用过多的桌面空间。本文将详细介绍如何在 Qt 项目中添加托盘图标,并通过资源系统(.qrc 文件…...

【WB 深度学习实验管理】利用 Hugging Face 实现高效的自然语言处理实验跟踪与可视化
本文使用到的 Jupyter Notebook 可在GitHub仓库002文件夹找到,别忘了给仓库点个小心心~~~ https://github.com/LFF8888/FF-Studio-Resources 在自然语言处理领域,使用Hugging Face的Transformers库进行模型训练已经成为主流。然而,随着模型复…...

基础入门-网站协议身份鉴权OAuth2安全Token令牌JWT值Authirization标头
知识点: 1、网站协议-http/https安全差异(抓包) 2、身份鉴权-HTTP头&OAuth2&JWT&Token 一、演示案例-网站协议-http&https-安全测试差异性 1、加密方式 HTTP:使用明文传输,数据在传输过程中可以被…...

C语言基础系列【3】VSCode使用
前面我们提到过VSCode有多么的好用,本文主要介绍如何使用VSCode编译运行C语言代码。 安装 首先去官网(https://code.visualstudio.com/)下载安装包,点击Download for Windows 获取安装包后,一路点击Next就可以。 配…...

MySQL-5.7.44安装(CentOS7)
目录 1、下载安装包并解压 2、创建数据目录与日志目录 3、设置环境变量 4、刷新环境变量 5、执行初始化 6、创建配置文件目录 7、新建配置文件 8、为安装目录赋予可执行权限 9、创建服务启动脚本 10、启动服务并将启动脚本加入开机自启动 11、查看服务状态 12、创建…...
服务端与多客户端照片的传输,recv,send
一、照片传输 server.c /* * 文件名称:server.c * 创 建 者: * 创建日期:2025年02月07日 * 描 述: */ #include <stdio.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h…...

龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...

【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...

家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...

现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...

HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...

使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...