设计模式详解(九):状态模式——State

状态模式详解

状态模式(State Pattern)是行为型设计模式的一种,它允许对象在内部状态发生改变时改变其行为,看起来像是改变了其类。状态模式通过将状态的行为封装到独立的状态类中,从而使得状态切换变得清晰且易于维护。


1. 什么是状态模式

状态模式主要解决的是对象在不同状态下表现出不同行为的问题。其核心思想是:

  • 状态切换:将状态转移逻辑放入状态对象中,而不是集中在一个类里。
  • 行为封装:将与特定状态相关的行为封装到独立的状态类中。

适用场景:

  1. 对象的行为依赖于其状态。
  2. 状态的数量相对有限,且可能需要频繁切换。

2. 状态模式的结构

状态模式的 UML 类图如下:

> currentState
> doAction()
> doAction()
Context
State
ConcreteStateA
ConcreteStateB

组件分析:

  1. Context(上下文)

    • 持有当前状态的引用。
    • 对客户端提供接口,并将请求委托给当前状态。
  2. State(状态接口)

    • 定义状态行为的公共接口。
  3. ConcreteState(具体状态类)

    • 实现具体状态的行为。
    • 包含可能导致状态切换的逻辑。

3. 实现代码示例

以下是一个简单的状态模式实现案例:

需求:

模拟一个电灯的开关,电灯有“开”和“关”两种状态。

实现代码

// 状态接口
public interface State {void handle(Context context);
}// 具体状态类 - 开灯状态
public class OnState implements State {@Overridepublic void handle(Context context) {System.out.println("灯已开启,切换到关闭状态。");context.setState(new OffState());}
}// 具体状态类 - 关灯状态
public class OffState implements State {@Overridepublic void handle(Context context) {System.out.println("灯已关闭,切换到开启状态。");context.setState(new OnState());}
}// 上下文类
public class Context {private State currentState;public Context(State initialState) {this.currentState = initialState;}public void setState(State state) {this.currentState = state;}public void request() {currentState.handle(this);}
}// 测试类
public class Main {public static void main(String[] args) {Context context = new Context(new OffState());// 模拟状态切换context.request(); // 输出:灯已关闭,切换到开启状态。context.request(); // 输出:灯已开启,切换到关闭状态。}
}

4. 状态模式的优缺点

优点

  1. 分离状态逻辑

    • 每个状态独立成类,职责单一,易于扩展和维护。
  2. 简化上下文类

    • 状态切换的逻辑被移到了具体状态类中,上下文类更加简洁。
  3. 符合开闭原则

    • 新增状态无需修改现有代码,只需添加新的状态类。

缺点

  1. 状态类增多

    • 每个状态需要一个类,可能导致类的数量较多。
  2. 可能增加复杂性

    • 在简单场景下,使用状态模式可能显得过于复杂。

5. 状态模式的应用场景

  1. 游戏开发

    • 游戏角色的不同状态(如行走、奔跑、跳跃等)。
  2. 工作流系统

    • 不同审批阶段的状态切换。
  3. 图形界面系统

    • 按钮的不同状态(启用、禁用、悬停、点击)。

6. 图文总结

通过状态模式,上下文类可以专注于请求的分发,而无需关心具体状态的实现。以下是其优雅之处的图示:

graph TDA[Context] -->|request()| B[State Interface]B --> C[ConcreteStateA]B --> D[ConcreteStateB]C -->|switch| DD -->|switch| C

状态模式在设计复杂系统时,能有效地组织状态行为,增强代码的可维护性。希望这篇文章对你理解状态模式有所帮助!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/35246.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Qt学习笔记第51到60讲

第51讲 记事本实现打开功能 回到第24个功能文件Notepad,给UI中的各个控件添加槽函数。 ①开始按钮 void Widget::on_btnOpen_clicked() {QString fileNameQFileDialog::getOpenFileName(this,tr("Open File"),"E:\\6_Qt Projects\\24_Notepad\\fi…

WPS解决Word文件引入excel对象文件无法打开提示“不能启动此对象...”的问题

一、问题现象 接收到了一份 Word文件,里面引入了一个Excel对象文件,双击时候,wps出现卡顿,过一会之后弹出错误提示:不能启动此对象... 二、解决方法 1.点击WPS左上角图标,并打开右上角设置,萱蕚…

# issue 8 TCP内部原理和UDP编程

TCP 通信三大步骤: 1 三次握手建立连接; 2 开始通信,进行数据交换; 3 四次挥手断开连接; 一、TCP内部原理--三次握手 【第一次握手】套接字A∶"你好,套接字B。我这儿有数据要传给你,建立连接吧。" 【第二次…

什么是人工智能?(Chapter 2)

Chapter 2: 大家到底在争论什么? 2022 年末,OpenAI 发布 ChatGPT 后不久,网上开始流传一个新的备忘录,它比其他任何东西都更能捕捉到这项技术的诡异之处。在大多数版本中,一个名为 "食人魔"&am…

OpenCV-平滑图像

二维卷积(图像滤波) 与一维信号一样,图像也可以通过各种低通滤波器(LPF)、高通滤波器(HPF)等进行过滤。LPF 有助于消除噪音、模糊图像等。HPF 滤波器有助于在图像中找到边缘。 opencv 提供了函数 **cv.filter2D()**&…

如何使用 Docker Compose 安装 Memos 自托管笔记应用

简介 Memos是一个自托管的开源笔记应用程序,专为个人组织和信息管理而设计。它允许用户高效地创建、存储和管理笔记,提供如Markdown支持、用户友好的界面和注重隐私的设计等功能。Memos可以在各种平台上运行,但使用Docker Compose可以简化部…

西部地区生活物资保供与城郊大仓基地高质量建设运营论坛西安市成功举办

2024 年 12 月 5日,由中国商业联合会、陕西省商务厅指导,中国商业联合会商贸物流与供应链分会、西安市发改委、西安市商务局主办,中企盟(北京)电商物流技术研究院、西安商业联合会、陕西省商贸物流供应链协会承办的“西…

[笔记] Windows 上 Git 安装详细教程:从零开始,附带每个选项解析

Git 是目前最流行的分布式版本控制系统之一,广泛应用于软件开发和项目管理中。对于 Windows 用户来说,正确安装和配置 Git 是开始使用 Git 的第一步。本文提供一份详细的指南,帮助你在 Windows 系统上顺利安装 Git,并解释每个安装…

五天SpringCloud计划——DAY3之服务治理(Nacos+OpenFeign+OKHttp)

一、引言 在微服务架构中,一个项目通常会被分为多个模块来降低耦合,但是通常情况下,一个项目中总会出现一种情况——一个模块内的方法需要调用另一个模块内的方法。本文就来使用NacosOpenFeignOKHttp帮助大家解决这个问题。 二、Nacos的使用…

go-blueprint create exit status 1

1. 异常信息 2024/12/06 10:59:19 Could not initialize go.mod in new project exit status 1 2024/12/06 10:59:19 Problem creating files for project. exit status 1 Error: exit status 12. 排查思路 手动进行go mod init查看手动的报错解决报错 3. 解决问题 发现是GO11…

Socket编程-tcp

1. 前言 在tcp套接字编程这里,我们将完成两份代码,一份是基于tcp实现普通的对话,另一份加上业务,client输入要执行的命令,server将执行结果返回给client 2. tcp_echo_server 与udp类似,前两步&#xff1…

Python使用Selenium自动实现表单填写之蛇年纪念币蛇钞预约(附源码,源码有注释解析,已测试可用

Python实现纪念币预约自动填写表单 声明:本文只做技术交流,不可用代码为商业用途,文末有源码下载,已测试可用。 Part 1 配置文件改写(源码 有详细的注释说明 读取配置文件,自己组数据库,录入信息 配置文件 Part 2 主函数 每一期的xpath路径都不一样 所以需要提前去网站…

【计算机网络】期末速成(2)

部分内容来源于网络,侵删~ 第五章 传输层 概述 传输层提供进程和进程之间的逻辑通信,靠**套接字Socket(主机IP地址,端口号)**找到应用进程。 传输层会对收到的报文进行差错检测。 比特流(物理层)-> 数据帧(数据链路层) -> 分组 / I…

Vue3网站锚点定位

网站上实现锚点定位的方法有很多&#xff0c;今天介绍vue3实现的定位效果的方式。通过scrollIntoViewh函数的行为&#xff0c;滑动至指定的容器。 一、样式布局 <template> <div style"width: 100%; display: flex;flex-direction: column;"><div …

微信小程序实现图片拖拽调换位置效果 -- 开箱即用

在编写类似发布朋友圈功能的功能时&#xff0c;需要实现图片的拖拽排序&#xff0c;删除图片等功能。 一、效果展示 **博主的小程序首页也采用了该示例代码&#xff0c;可以在威信中搜索&#xff1a;我的百宝工具箱 二、示例代码 1.1、在自己的小程序中创建组件 1.2、组件…

五、docker的网络模式

五、docker的网络模式 5.1 Docker的四种网络模式 当你安装docker时&#xff0c;它会自动创建三个网络&#xff0c;可使用如下命令查看&#xff1a; [rootlocalhost ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 7390284b02d6 bridge bridge lo…

ros项目dual_arm_pick-place(对比moveit配置助手生成的文件)

目录 前言正文gazebo_controllers.yaml变更ros_controllers.yaml变更simple_moveit_controllers.yaml变更moveit_planning_execution.launch变更ros_controllers.launch变更其他文件 汇总总结 前言 在本专栏前文中讲到&#xff0c;作者有moveit配置助手导出的包marmbots&#…

【uni-app 微信小程序】新版本发布提示用户进行更新

知识准备 uni.getUpdateManager文档介绍 不支持APP与H5&#xff0c;所以在使用的时候要做好平台类型的判断&#xff0c;如何判断&#xff0c;参考条件编译处理多端差异 代码参考 export const updateApp () > {const updateManager uni.getUpdateManager()updateManag…

Java-操作xls替换文本或图片

准备xls模板文件&#xff1a;template.xls 要求根据不同的产品型号和图片&#xff0c;插入到模板文件中&#xff0c;然后再填充产品信息。 准备需要替换的图片和数据 功能实现 package net.work.controller.base;import io.swagger.annotations.Api; import io.swagger.annot…

.Net学习

1 什么是.NET Core .NET是开发平台&#xff0c;.NET Framework、.NET Core、Xamaarin/Mono的统称。 .NET Framework是只能在Windows上开发的技术 .NET Core是可以跨平台开发的技术 Xamaarin/Mono是移动端开发的技术 .NET Core&#xff1a;跨平台、免费、开源&#xff0c;可…