当前位置: 首页 > news >正文

详解状态模式

引言

        水有固态、液态、气态三种状态,在不同条件下这三种状态可以相互转化。同样在软件设计中,有些对象也有不同的状态,不同状态的行为不同,状态模式就是用来处理这种情况的。

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相关代码&#xff0c;需注意: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踩坑记录

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

亚博microros小车-原生ubuntu支持系列:25 二维码控制运动

二维码识别 安装依赖 pip3 install pyzbarsudo apt install libzbar-dev 在用小车识别之前&#xff0c;先用电脑的摄像头测试下基本的识别 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使用

说明&#xff1a;本文介绍Spring Boot Actuator的使用&#xff0c;关于Spring Boot Actuator介绍&#xff0c;下面这篇博客写得很好&#xff0c;珠玉在前&#xff0c;我就不多介绍了。 Spring Boot Actuator 简单使用 项目里引入下面这个依赖 <!--Spring Boot Actuator依…...

【AI应用】免费的文本转语音工具:微软 Edge TTS 和 开源版 ChatTTS 对比

【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】【读书与思考】【AI应用】 我试用了下Edge TTS&#xff0c;感觉还不错&#xff0c;不过它不支持克隆声音&#xff08;比如自己的声音&#xff09; 微软 Edge TTS 和 开源版 ChatTTS 都是免费的 文本转语音&…...

如何在 Qt 中添加和使用系统托盘图标

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

【WB 深度学习实验管理】利用 Hugging Face 实现高效的自然语言处理实验跟踪与可视化

本文使用到的 Jupyter Notebook 可在GitHub仓库002文件夹找到&#xff0c;别忘了给仓库点个小心心~~~ https://github.com/LFF8888/FF-Studio-Resources 在自然语言处理领域&#xff0c;使用Hugging Face的Transformers库进行模型训练已经成为主流。然而&#xff0c;随着模型复…...

基础入门-网站协议身份鉴权OAuth2安全Token令牌JWT值Authirization标头

知识点&#xff1a; 1、网站协议-http/https安全差异&#xff08;抓包&#xff09; 2、身份鉴权-HTTP头&OAuth2&JWT&Token 一、演示案例-网站协议-http&https-安全测试差异性 1、加密方式 HTTP&#xff1a;使用明文传输&#xff0c;数据在传输过程中可以被…...

C语言基础系列【3】VSCode使用

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

MySQL-5.7.44安装(CentOS7)

目录 1、下载安装包并解压 2、创建数据目录与日志目录 3、设置环境变量 4、刷新环境变量 5、执行初始化 6、创建配置文件目录 7、新建配置文件 8、为安装目录赋予可执行权限 9、创建服务启动脚本 10、启动服务并将启动脚本加入开机自启动 11、查看服务状态 12、创建…...

服务端与多客户端照片的传输,recv,send

一、照片传输 server.c /* * 文件名称&#xff1a;server.c * 创 建 者&#xff1a; * 创建日期&#xff1a;2025年02月07日 * 描 述&#xff1a; */ #include <stdio.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h…...

Node.js——util工具模块

util工具模块1、util模块概述2、util模块的使用2.1、格式化输出字符串2.2、将对象转换为字符串&#xff08;调试&#xff09;2.3、实现对象间的原型继承2.4、转换异步函数的风格2.5、判断是否为指定类型的内置对象2.6、其它方法1、util模块概述 util模块是Node.js的内置模块&a…...

2026大厂校招笔试指南(高频考点+真实趋势)

关注 霍格沃兹测试学院公众号&#xff0c;回复「资料」&#xff0c;领取人工智能测试开发技术合集很多人现在卡在同一个问题上&#xff1a;题也刷了&#xff0c;时间也花了&#xff0c;但一到笔试还是过不了。你可能也有这种感觉&#xff1a;简单题会做&#xff0c;中等题卡住&…...

OWL ADVENTURE惊艳案例:风格迁移与艺术画作生成

OWL ADVENTURE惊艳案例&#xff1a;风格迁移与艺术画作生成 每次看到那些世界名画&#xff0c;你是不是也想过&#xff0c;要是能把自己的照片也变成那样该多好&#xff1f;以前这得靠专业画师花上好几天&#xff0c;现在&#xff0c;有了OWL ADVENTURE这样的AI模型&#xff0…...

告别复杂配置!OSHI+JNA五分钟搞定Windows/Linux/macOS硬件信息采集

五分钟极简指南&#xff1a;用OSHIJNA实现全平台硬件监控零门槛接入 运维工程师小张最近接手了公司混合云环境下的服务器监控任务。当他面对Windows服务器、Linux虚拟机、macOS开发机三种不同系统时&#xff0c;传统方案需要分别调用WMI、/proc文件系统和system_profiler&#…...

4个硬核特性解决开发者存储管理难题

4个硬核特性解决开发者存储管理难题 【免费下载链接】czkawka Multi functional app to find duplicates, empty folders, similar images etc. 项目地址: https://gitcode.com/GitHub_Trending/cz/czkawka 一、存储困境诊断&#xff1a;开发者面临的四大存储挑战 识别…...

PID调参翻车实录:STM32驱动编码电机时,P值过大为何电机啸叫还振荡?

PID调参实战&#xff1a;STM32编码电机啸叫与振荡问题深度解析 当你在深夜实验室里第一次听到电机发出刺耳的啸叫声&#xff0c;同时观察到示波器上速度曲线像过山车一样上下震荡时&#xff0c;那种既困惑又兴奋的感觉&#xff0c;相信每个做过电机控制的工程师都深有体会。这不…...

新手入门DetectionLab:10个步骤掌握企业网络安全检测基础

新手入门DetectionLab&#xff1a;10个步骤掌握企业网络安全检测基础 【免费下载链接】DetectionLab clong/DetectionLab: DetectionLab是一个开源项目&#xff0c;旨在建立一个高度可配置的虚拟环境以模拟企业网络&#xff0c;用于检测恶意活动、演练入侵检测系统&#xff08;…...

别怕C++!手把手拆解TinyML测试框架:用micro_test.h给你的嵌入式AI代码加个‘保险丝’

嵌入式AI开发者的测试实战指南&#xff1a;用micro_test.h构建TinyML质量防线 在资源受限的微控制器上开发AI应用时&#xff0c;一个被反复验证的真理是&#xff1a;没有自动化测试的代码就像没有安全网的走钢丝。当你的神经网络模型需要在仅有几KB内存的设备上运行时&#xff…...

App UI自动化项目模板

完整的App UI自动化项目模板 以下是一套工程化、可复用、易维护的App UI自动化项目模板&#xff0c;基于PythonAppium2pytest实现&#xff0c;包含BasePage封装、PO页面类、数据驱动、日志/报告/配置分离等核心工程化配置&#xff0c;你只需替换业务相关的元素定位、操作逻辑、…...

BACnet4j实战:从模拟设备到点位数据采集的完整流程解析

1. BACnet4j与工业物联网数据采集入门 第一次接触BACnet协议时&#xff0c;我被各种专业术语搞得晕头转向。直到用BACnet4j成功读取到第一个温度传感器的数据&#xff0c;才真正理解这个协议的价值。BACnet/IP就像工业设备间的普通话&#xff0c;而BACnet4j就是让Java程序能说这…...