23种设计模式-状态(State)设计模式
文章目录
- 一.什么是状态模式?
- 二.状态模式的结构
- 三.状态模式的应用场景
- 四.状态模式的优缺点
- 五.状态模式的C++实现
- 六.状态模式的JAVA实现
- 七.代码解释
- 八.总结
类图: 状态设计模式类图
一.什么是状态模式?
状态模式(State Pattern)是一种行为型设计模式,允许对象在其内部状态改变时改变其行为,看起来就像对象改变了其类。状态模式通过将状态封装为独立的类,使得对象的行为能够根据内部状态动态地改变。
在状态模式中,Context(环境类)持有一个指向State(状态接口)的引用对象,并通过该对象来进行状态切换。具体的状态通过实现状态接口的不同子类来进行封装。
二.状态模式的结构
- Context(环境类):用于维护当前状态,并在特定操作时切换状态。它持有一个State对象的引用,用来对状态进行操作。
- State(状态接口):定义了一个接口,声明了每个具体状态需要实现的行为。
- ConcreteStateA 和 ConcreteStateB(具体状态类):实现State接口的不同子类,表示对象在不同状态下的行为。
三.状态模式的应用场景
- 对象行为依赖于状态,且状态在运行时变化:如电梯的状态(上升、下降、停止)、游戏角色的状态(跑步、跳跃、静止)。
- 条件语句过多:当对象中有大量if-else或switch语句判断状态时,可以考虑使用状态模式进行优化。
四.状态模式的优缺点
-
优点:
- 封装状态转换:将状态与相关行为封装在一个类中,便于维护和扩展。
- 避免条件判断:通过多态替代了条件判断,代码更具可读性和扩展性。
-
缺点:
- 类数量增加:每个状态需要一个类,可能会导致类数量较多。
五.状态模式的C++实现
#include <iostream>
#include <memory>// 前置声明,避免循环引用
class State;// 环境类(Context)
class Context {
private:std::shared_ptr<State> state; // 当前状态public:// 设置当前状态void setState(std::shared_ptr<State> newState) {state = newState;}// 执行请求,调用当前状态的Handle方法void request();
};// 状态接口(State)
class State {
public:virtual void handle(Context& context) = 0; // 定义纯虚函数,具体状态类需实现
};// 具体状态类 A(ConcreteStateA)
class ConcreteStateA : public State {
public:void handle(Context& context) override {std::cout << "ConcreteStateA handling request.\n";// 状态切换:可以切换到状态 Bcontext.setState(std::make_shared<ConcreteStateB>());}
};// 具体状态类 B(ConcreteStateB)
class ConcreteStateB : public State {
public:void handle(Context& context) override {std::cout << "ConcreteStateB handling request.\n";// 状态切换:可以切换回状态 Acontext.setState(std::make_shared<ConcreteStateA>());}
};// 环境类方法的实现
void Context::request() {if (state) {state->handle(*this); // 调用当前状态的 handle 方法}
}// 测试代码
int main() {Context context;// 初始化状态为 Acontext.setState(std::make_shared<ConcreteStateA>());// 执行多次请求,测试状态切换context.request(); // ConcreteStateA 处理请求,然后切换到 ConcreteStateBcontext.request(); // ConcreteStateB 处理请求,然后切换到 ConcreteStateAcontext.request(); // ConcreteStateA 处理请求,然后切换到 ConcreteStateBreturn 0;
}
六.状态模式的JAVA实现
// 抽象状态类
abstract class State {public abstract void Handle(Context context);
}// 具体状态A
class ConcreteStateA extends State {@Overridepublic void Handle(Context context) {System.out.println("ConcreteStateA: Handling request and transitioning to ConcreteStateB.");context.setState(new ConcreteStateB());}
}// 具体状态B
class ConcreteStateB extends State {@Overridepublic void Handle(Context context) {System.out.println("ConcreteStateB: Handling request and transitioning to ConcreteStateA.");context.setState(new ConcreteStateA());}
}// 环境类 (Context)
class Context {private State state;public Context(State state) {this.state = state;}public void setState(State state) {this.state = state;}public void Request() {if (state != null) {state.Handle(this);}}
}// 客户端代码
public class StatePatternDemo {public static void main(String[] args) {// 初始状态为 ConcreteStateAContext context = new Context(new ConcreteStateA());// 调用多次 Request,观察状态切换context.Request(); // 从 A 切换到 Bcontext.Request(); // 从 B 切换到 Acontext.Request(); // 再次从 A 切换到 B}
}
七.代码解释
- Context 类:
- Context类持有一个指向State的指针(使用智能指针std::shared_ptr来管理状态对象的生命周期)。
- 它包含一个request()方法,用于请求当前状态处理相应的操作。
- setState()方法用于切换状态,方便在运行时改变state的引用指向不同的State对象。
- State 接口:
- State接口中定义了一个纯虚函数handle(),表示不同状态下的行为。
- Context通过调用state->handle(*this)来执行当前状态的具体行为。
- ConcreteStateA 和 ConcreteStateB:
- ConcreteStateA和ConcreteStateB是State接口的具体实现类,每个类都定义了各自的handle()方法。
- 在ConcreteStateA::handle()中,Context的状态被切换为ConcreteStateB,而在ConcreteStateB::handle()中,状态切换回ConcreteStateA。
- 这种状态切换体现了状态模式的核心思想,即状态内部控制状态转换,客户端不需要关心状态如何切换。
- 测试代码:
- 在main函数中,创建Context对象context,并将初始状态设为ConcreteStateA。
- 通过多次调用request()方法,可以看到状态在ConcreteStateA和ConcreteStateB之间切换,体现出对象行为随状态变化而变化的特点。
八.总结
状态模式是一种非常适合解决对象行为依赖于状态变化的设计模式。通过将状态封装为独立的类,状态模式使得代码更加清晰和易于维护,避免了条件判断语句的冗余和复杂性。每个具体状态类不仅实现了各自的行为,还决定了状态切换的逻辑,从而让状态之间的转换更为灵活。
关键点:
- 状态模式封装了对象内部的状态变化逻辑,使得对象的行为可以动态改变。
- 通过多态,状态模式避免了条件判断,使代码更具可扩展性。
- 状态切换由具体状态类控制,客户端只需与Context交互,降低了耦合度。
相关文章:

23种设计模式-状态(State)设计模式
文章目录 一.什么是状态模式?二.状态模式的结构三.状态模式的应用场景四.状态模式的优缺点五.状态模式的C实现六.状态模式的JAVA实现七.代码解释八.总结 类图: 状态设计模式类图 一.什么是状态模式? 状态模式(State Pattern&…...

EventListener与EventBus
EventListener JDK JDK1.1开始就提供EventListener,一个标记接口,源码如下: /*** A tagging interface that all event listener interfaces must extend.*/ public interface EventListener { }JDK提供的java.util.EventObject࿱…...

Facebook为什么注册失败了?该怎么解决?
有时候用户在尝试注册Facebook账号时可能会遇到各种问题,导致注册失败或遇到困难。小编会为大家分析Facebook注册失败的可能原因,并提供解决方法,帮助大家顺利完成注册流程。 一、Facebook注册失败的可能原因 1. 账号信息问题: …...
前端数据可视化思路及实现案例
目录 一、前端数据可视化思路 (一)明确数据与目标 (二)选择合适的可视化图表类型 (三)数据与图表的绑定及交互设计 (四)页面布局与样式设计 二、具体案例:使用 Ech…...

【DVWA】Brute Force暴力破解实战
问尔辈 何等样人 自摸心头 再来求我;若汝能 克存忠孝 持身正直 不拜何妨 1.Brute Force(Low) 相关的代码分析 if( isset( $_GET[ Login ] ) ) {// Get username$user $_GET[ username ];// Check the database$query "SELECT * FROM users WHERE user $…...

23种设计模式速记法
前言 在软件开发的过程中,设计模式作为解决常见问题的通用模板,一直是开发者的重要工具。尤其是在面临复杂系统架构和需求变化时,设计模式不仅能够提升代码的可复用性和扩展性,还能大大提高团队之间的协作效率。然而,…...

第7章硬件测试-7.3 功能测试
7.3 功能测试 7.3.1 整机规格测试7.3.2 整机试装测试7.3.3 DFX测试 功能测试包括整机规格、整机试装和整机功能测试,是整机结构和业务相关的测试。 7.3.1 整机规格测试 整机规格测试包括尺寸、重量、温度、功耗等数据。这些测试数据与设计规格进行比对和校验&…...

动态规划子数组系列一>等差数列划分
题目: 解析: 代码: public int numberOfArithmeticSlices(int[] nums) {int n nums.length;int[] dp new int[n];int ret 0;for(int i 2; i < n; i){dp[i] nums[i] - nums[i-1] nums[i-1] - nums[i-2] ? dp[i-1]1 : 0;ret dp[i…...

《Python浪漫的烟花表白特效》
一、背景介绍 烟花象征着浪漫与激情,将它与表白结合在一起,会创造出别具一格的惊喜效果。使用Python的turtle模块,我们可以轻松绘制出动态的烟花特效,再配合文字表白,打造一段专属的浪漫体验。 接下来,让…...
什么是RESTful API,有什么特点
RESTful API 概述 什么是 RESTful API? RESTful API 是基于 Representational State Transfer(表现层状态转移)架构风格的 Web 服务接口。REST 是一种设计风格,而不是具体的协议或标准。它定义了一组约束和最佳实践,…...

友思特新闻 | 友思特荣获广州科技创新创业大赛智能装备行业赛初创组优胜企业!
2024年11月19日,第十三届中国创新创业大赛(广东广州赛区)暨2024年广州科技创新创业大赛智能装备行业赛颁奖典礼隆重举行。 赛事奖项介绍:广州科技创新创业大赛智能装备行业赛 第十三届“中国创新创业大赛(广东广州赛区…...
CSS中calc语法不生效
问题起因 在使用calc时发现无法生效,写法是: height:calc(100vh-100px);页面无效果,加空格后就发现有效果了: height:calc(100vh - 100px);这是为什么? calc是什么? css3 的计算属性,用于动态…...

国标GB28181视频平台EasyCVR视频融合平台H.265/H.264转码业务流程
在当今数字化、网络化的视频监控领域,大中型项目对于视频监控管理平台的需求日益增长,特别是在跨区域、多设备、高并发的复杂环境中。EasyCVR视频监控汇聚管理平台正是为了满足这些需求而设计的,它不仅提供了全面的管理功能,还支持…...
ES6 模板字符串详解
ES6 模板字符串详解 ES6(ECMAScript 6)引入了模板字符串(Template Literals),这是一种新的字符串字面量语法,使用反引号()来定义字符串。模板字符串不仅支持多行字符串,…...

浏览器插件启动本地程序
浏览器插件支持启动本地程序,且支持win、mac、linux多个平台,使用的是nativeMessaging。nativeMessaging官方api说明。nativeMessaging支持启动本地程序且进行通信。 我们直接拿官方提供的例子进行说明,github地址。 以win为例 1、添加注册…...

Ubuntu ESP32开发环境搭建
文章目录 ESP32开发环境搭建安装ESP-IDF搭建一个最小工程现象 ESP32开发环境搭建 最近有个小项目需要用到能够联网的mcu驱动,准备玩玩esp的芯片,记录下ESP32开发环境搭建的过程。 ESP-IDF 是乐鑫科技为其 ESP32 系列芯片提供的官方开发框架。这个框架主…...
【gitlab】部署
直接RPM安装 部署的方式是:使用外部的nginx作为代理,使用https方式。 1、下载安装文件 gitlab-ce-17.0.3-ce.0.el7.x86_64.rpm 2、安装 yum install gitlab-ce-17.0.3-ce.0.el7.x86_64.rpm 或者安装yum源在线安装: 添加镜像源:新建 /et…...

vue中路由缓存
vue中路由缓存 问题描述及截图解决思路关键代码及打印信息截图 问题描述及截图 在使用某一平台时发现当列表页码切换后点击某一卡片进入详情页后,再返回列表页时页面刷新了。这样用户每次看完详情回到列表页都得再重新输入自己的查询条件,或者切换分页到…...
Github 2024-11-18 开源项目周报 Top15
根据Github Trendings的统计,本周(2024-11-18统计)共有15个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目8TypeScript项目4Jupyter Notebook项目2Go项目2Shell项目1OpenHands: 人工智能驱动的软件开发代理平台 创建周期:195 天开发语言:P…...

GRCNN使用onnxruntime和tensorrt推理
下载GRCNN项目:https://github.com/skumra/robotic-grasping.git 导出onnx模型: import torchnet torch.load("trained-models/jacquard-rgbd-grconvnet3-drop0-ch32/epoch_42_iou_0.93") x torch.rand(1, 4, 300, 300).cuda() torch.onnx.…...

地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...

【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...

基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...