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

状态模式(State)

状态模式是一种行为设计模式,允许一个对象在其内部状态改变时改变它的行为,使其看起来修改了自身所属的类。其别名为状态对象(Objects for States)。

State is a behavior design pattern that allows an object to change its behavior when its internal state changes,
making it appear to have modified the class it belongs to.

在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象叫做有状态的(stateful)对象,这样的对象状态是从事先定义好的一系列值中取出的。
当一个这样的对象与外部事件产生互动时,其内部状态就会改变,从而使得系统的行为也随之发生变化。
在UML中可以使用状态图来描述对象状态的变化。

结构设计

Context,上下文类,保存了对于一个Concrete State对象(具体状态对象)的引用,并会将所有与该状态相关的工作委派给它。上下文通过状态接口与状态对象交互。
State,状态基类,接口会声明特定于状态的方法。
Concrete State,具体状态类,会自行实现特定于状态的方法。当多个状态中包含相似代码,可以提供一个封装有部分通用行为的中间抽象类。
状态对象可存储对于上下文对象的反向引用。状态对象可以通过该引用从上下文处获取所需信息,并且能触发状态转移。但这可能会带来对象的循环引用,在实际使用时,要通过对象传参的方式使用。
状态模式类图表示如下:
请添加图片描述

状态模式可能看上去与策略模式相似,但有一个关键性的不同——在状态模式中,特定状态知道其他所有状态的存在,且能触发从一个状态到另一个状态的转换,而策略则几乎完全不知道其他策略的存在。

伪代码实现

接下来将使用代码介绍下状态模式的实现。

// 1、State,状态接口,声明特定于状态的方法
public interface IState {void handle(StateContext context);void doSomething();
}// 2、具体状态类,会自行实现特定于状态的方法,这里特定状态知道其他所有状态的存在,且能触发从一个状态到另一个状态的转换
public class ConcreteStateA implements IState {private static ConcreteStateA state;// 这里的单例实现暂不考虑并发场景public static IState getInstance() {if (state == null) {state = new ConcreteStateA();}return state;}@Overridepublic void handle(StateContext context) {doSomething();context.setCurrentState(ConcreteStateB.getInstance());}@Overridepublic void doSomething() {System.out.println("do some thing in the concrete A instance");}
}
public class ConcreteStateB implements IState {private static ConcreteStateB state;// 这里的单例实现暂不考虑并发场景public static IState getInstance() {if (state == null) {state = new ConcreteStateB();}return state;}@Overridepublic void handle(StateContext context) {doSomething();context.setCurrentState(ConcreteStateA.getInstance());}@Overridepublic void doSomething() {System.out.println("do some thing in the concrete B instance");}
}// 3、状态上下文类,保存了对于一个Concrete State对象(具体状态对象)的引用,并会将所有与该状态相关的工作委派给它。  
// 上下文通过状态接口与状态对象交互。  
public class StateContext {private IState currentState;public StateContext(IState defaultState) {this.currentState = defaultState;}public IState getCurrentState() {return this.currentState;}public void setCurrentState(IState newState) {this.currentState = newState;}public void request() {currentState.handle(this);}
}// 4、客户端
public class StateClient {public void test() {StateContext stateContext = new StateContext(new ConcreteStateA());stateContext.request();stateContext.request();stateContext.request();}
}

适用场景

在以下情况下可以考虑使用状态模式:
(1) 对象的行为依赖于它的状态(属性)并且可以根据它的状态改变而改变它的相关行为,同时状态的数量非常多且与状态相关的代码会频繁变更的话,可以考虑使用状态模式。
(2) 代码中包含大量与对象状态有关的条件语句,这些条件语句的出现,会导致代码的可维护性和灵活性变差,不能方便地增加和删除状态,
使客户类与类库之间的耦合增强。在这些条件语句中包含了对象的行为,而且这些条件对应于对象的各种状态。
(3) 当相似状态和基于条件的状态机转换中存在许多重复代码时,可考虑使用状态模式。状态模式能够生成状态类层次结构,通过将公用代码抽取到抽象基类中来减少重复。

优缺点

状态模式有以下优点:
(1) 封装了转换规则。调用方无需关心状态转换的实现。
(2) 符合开闭原则。无需修改已有状态类和上下文就能引入新状态。
(3) 符合单一职责原则。将与特定状态相关的代码放在单独的类中。
(4) 消除了可能存在的条件语句。通过消除臃肿的状态机条件语句简化上下文代码。
(5) 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
但是该模式也存在以下缺点:
(1) 如果状态机只有很少的几个状态, 或者很少发生改变, 那么应用该模式可能会显得小题大作。
(2) 增加系统类和对象的个数。
(3) 实现较为复杂,如果使用不当将导致程序结构和代码的混乱。
(4) 对“开闭原则”的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。

参考

《设计模式 可复用面向对象软件的基础》 Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides 著, 李英军, 马晓星等译
https://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/state.html 状态模式
https://refactoringguru.cn/design-patterns/state 状态模式
https://www.runoob.com/design-pattern/state-pattern.html 状态模式
https://www.cnblogs.com/adamjwh/p/10926952.html 简说设计模式——状态模式

相关文章:

状态模式(State)

状态模式是一种行为设计模式,允许一个对象在其内部状态改变时改变它的行为,使其看起来修改了自身所属的类。其别名为状态对象(Objects for States)。 State is a behavior design pattern that allows an object to change its behavior when its inter…...

【uniapp】样式合集

1、修改uni-data-checkbox多选框的样式为单选框的样式 我原先是用的单选&#xff0c;但是单选并不支持选中后&#xff0c;再次点击取消选中&#xff1b;所以我改成了多选&#xff0c;然后改变多选样式&#xff0c;让他看起来像单选 在所在使用的页面上修改样式即可 <uni-d…...

【Spring框架】SpringBoot统一功能处理

目录 用户登录权限校验用户登录拦截器排除所有静态资源练习&#xff1a;登录拦截器拦截器实现原理 统一异常处理统一数据返回格式为什么需要统⼀数据返回格式&#xff1f;统⼀数据返回格式的实现 用户登录权限校验 用户登录拦截器 1.自定义拦截器 package com.example.demo.…...

51单片机学习--按键控制流水灯模式定时器时钟

TMOD负责确定T0和T1的工作模式&#xff0c;TCON控制T0和T1的启动或停止计数&#xff0c;同时包含定时器状态 TF1&#xff1a;定时器1溢出标志 TF0&#xff1a;定时器0溢出标志 0~65535 每隔1微秒计数器1&#xff0c;总时间65535微秒&#xff0c;赋上初值64535&#xff0c;则只…...

Django教程_编程入门自学教程_菜鸟教程-免费教程分享

教程简介 Django是一个开放源代码的Web应用框架&#xff0c;由Python写成。采用了MTV的框架模式&#xff0c;即模型M&#xff0c;视图V和模版T。它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的&#xff0c;即是CMS&#xff08;内容管理系统&#xf…...

VGG卷积神经网络-笔记

VGG卷积神经网络-笔记 VGG是当前最流行的CNN模型之一&#xff0c; 2014年由Simonyan和Zisserman提出&#xff0c; 其命名来源于论文作者所在的实验室Visual Geometry Group。 测试结果为&#xff1a; 通过运行结果可以发现&#xff0c;在眼疾筛查数据集iChallenge-PM上使用VGG…...

Python爬虫如何实现IP代理池搭建

大家好&#xff0c;作为一名IP代理产品供应商&#xff0c;我知道很多人在使用Python爬虫时遇到了一些麻烦。有时候&#xff0c;我们的爬虫在爬取过程中会被目标网站识别并封禁IP&#xff0c;导致我们的爬取任务受阻。今天我要分享的就是如何搭建一个高效稳定的IP代理池&#xf…...

单例模式:保证一个类只有一个实例

单例模式&#xff1a;保证一个类只有一个实例 什么是单例模式&#xff1f; 在软件开发中&#xff0c;有些类只需要一个实例&#xff0c;比如数据库连接池、线程池等。单例模式就是一种设计模式&#xff0c;用于确保一个类只有一个实例&#xff0c;并提供一个全局访问点。 实…...

【新版系统架构补充】-七层模型

网络功能和分类 计算网络的功能 &#xff1a;数据通信、资源共享、管理集中化、实现分布式处理、负载均衡 网络性能指标&#xff1a;速率、带宽&#xff08;频带宽度或传送线路速率&#xff09;、吞吐量、时延、往返时间、利用率 网络非性能指标&#xff1a;费用、质量、标准化…...

第2章 C语言概述

本章介绍以下内容&#xff1a; 运算符&#xff1a; 函数&#xff1a;main()、printf() 编写一个简单的C程序 创建整型变量&#xff0c;为其赋值并在屏幕上显示其值 换行字符 如何在程序中写注释&#xff0c;创建包含多个函数的程序&#xff0c;发现程序的错误 什么是关键字 C程…...

vscode vue3开发常用插件(附Prettier格式化配置)

必不可少插件(名称可能不全)&#xff1a; 1、Chinese (Simplified) (简体中文) Language 2、Prettier - Code formatter 3、Vue 3 Snippets 4、Vue Language Features (Volar) 可选插件&#xff1a; 5、Auto Close Tag 6、Vue Theme Prettier格式化配置&#xff1a; 按ctr…...

【微信小程序】van-uploader实现文件上传

使用van-uploader和wx.uploadFile实现文件上传&#xff0c;后端使用ThinkPHP。 1、前端代码 json&#xff1a;引入van-uploader {"usingComponents": {"van-uploader": "vant/weapp/uploader/index"} }wxml&#xff1a;deletedFile是删除文件函…...

人工智能在计算机视觉中的应用与挑战

引言 计算机视觉是人工智能领域的一个重要分支&#xff0c;旨在让计算机能够像人一样理解和解释视觉信息&#xff0c;实现图像和视频的自动识别、理解和分析。计算机视觉技术已经在许多领域产生了深远的影响&#xff0c;如人脸识别、自动驾驶、医学影像分析等。本篇博客将深入…...

以太网接口指示灯状态分析和电路设计

一、RJ45以太网连接器介绍 以带网络隔离变压器的RJ45接头为例&#xff0c;如HR911105A&#xff0c;其技术参数如下 原理框图 指示灯部分 二、PHY芯片 phy芯片以DP83848CVV/NOPB为例&#xff0c;查看数据手册。引脚26&#xff0c;引脚27和引脚28和LED灯相关&#xff0c;如下截…...

Redis的基础

一、进入redis 内部 / 关闭 # 方式一&#xff1a; // 进入redis redis-cli // 有密码输入密码 &#xff1a;auth [username] password auth 123456 # 方式二&#xff1a; // 进入redis 并且输入密码 redis-cli -a 123456// 如果在docker 里面的则可以 docker exec -it redis…...

LeetCode 626. 换座位

题目链接&#xff1a;LeetCode 626. 换座位 题目描述 表名&#xff1a;Seat 编写SQL查询来交换每两个连续的学生的座位号。如果学生的数量是奇数&#xff0c;则最后一个学生的id不交换。 按 id 升序 返回结果表。 查询结果格式如下所示。 示例1&#xff1a; 题目分析 如…...

华为、阿里巴巴、字节跳动 100+ Python 面试问题总结(六)

系列文章目录 个人简介&#xff1a;机电专业在读研究生&#xff0c;CSDN内容合伙人&#xff0c;博主个人首页 Python面试专栏&#xff1a;《Python面试》此专栏面向准备面试的2024届毕业生。欢迎阅读&#xff0c;一起进步&#xff01;&#x1f31f;&#x1f31f;&#x1f31f; …...

hash 模式和 history 模式的实现原理

hash 模式和 history 模式的实现原理&#xff1a; #后面的 hash 值的变化不会导致浏览器向服务器发出请求&#xff0c;浏览器不发出请求&#xff0c;就不会刷新页面。通过监听 hashchange 事件的变化可以知道 hash 值发生了哪些变化&#xff0c;然后根据 hash 值的变化来实现更…...

并发编程Part 2

1. JMM 问题&#xff1a;请你谈谈你对volatile的理解? volitile 是 Java 虚拟机提供的一种轻量级的同步机制 &#xff0c;三大特性&#xff1a; 保证可见性 不保证原子性 禁止指令重排 线程之间如何通信&#xff1f; 通信是指线程之间以如何来交换信息。一般线程之间的通信…...

springboot异步多线程的实现

1、配置线程池相关参数 package com.xxx.test.config;import lombok.extern.slf4j.Slf4j; import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...

人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent

安全大模型训练计划&#xff1a;基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标&#xff1a;为安全大模型创建高质量、去偏、符合伦理的训练数据集&#xff0c;涵盖安全相关任务&#xff08;如有害内容检测、隐私保护、道德推理等&#xff09;。 1.1 数据收集 描…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...

9-Oracle 23 ai Vector Search 特性 知识准备

很多小伙伴是不是参加了 免费认证课程&#xff08;限时至2025/5/15&#xff09; Oracle AI Vector Search 1Z0-184-25考试&#xff0c;都顺利拿到certified了没。 各行各业的AI 大模型的到来&#xff0c;传统的数据库中的SQL还能不能打&#xff0c;结构化和非结构的话数据如何和…...

macOS 终端智能代理检测

&#x1f9e0; 终端智能代理检测&#xff1a;自动判断是否需要设置代理访问 GitHub 在开发中&#xff0c;使用 GitHub 是非常常见的需求。但有时候我们会发现某些命令失败、插件无法更新&#xff0c;例如&#xff1a; fatal: unable to access https://github.com/ohmyzsh/oh…...