Java设计模式:行为型模式→状态模式

news2025/2/7 1:16:41

Java 状态模式详解

1. 定义

状态模式(State Pattern)是一种行为型设计模式,它允许对象在内部状态改变时改变其行为。状态模式通过将状态需要的行为封装在不同的状态类中,实现对象行为的动态改变。该模式的核心思想是分离不同状态的行为,并利用状态对象替代传统的条件判断语句。

2. 基本思想

状态模式的基本思想是将对象的状态封装成独立的状态类,并通过状态对象来控制行为的切换。当对象的状态变化时,它会切换到新的状态,相应的行为也会随之改变。通过这种方式,状态模式使得状态管理更加清晰,减少了复杂的条件判断,提高了代码的可维护性。

3. 基本原理

状态模式主要包括以下几个组成部分:

  • 上下文(Context):维护当前状态,并定义客户端与具体状态之间的交互。上下文包含一个对状态对象的引用。
  • 状态接口(State):定义了状态的行为接口,所有具体状态类需要实现该接口。
  • 具体状态类(Concrete State):实现状态接口,并实现与具体状态相关的行为。
    在这里插入图片描述

更多实用资源:

http://sj.ysok.net/jydoraemon 访问码:JYAM

4. 实现方式

4.1 基本实现

4.1.1 状态接口

定义一个状态接口,描述状态应实现的方法:

public interface State {
    void doAction(Context context);
}
4.1.2 上下文类

定义上下文类,维护对状态的引用:

public class Context {
    private State state;

    public void setState(State state) {
        this.state = state;
    }

    public State getState() {
        return state;
    }

    public void request() {
        state.doAction(this);
    }
}
4.1.3 具体状态类

实现具体状态类,定义具体的行为:

public class ConcreteStateA implements State {
    @Override
    public void doAction(Context context) {
        System.out.println("State A Action.");
        context.setState(this); // 设置当前状态为 State A
    }
}

public class ConcreteStateB implements State {
    @Override
    public void doAction(Context context) {
        System.out.println("State B Action.");
        context.setState(this); // 设置当前状态为 State B
    }
}
4.1.4 客户端代码

客户端代码使用状态模式:

public class Client {
    public static void main(String[] args) {
        Context context = new Context();
        
        ConcreteStateA stateA = new ConcreteStateA();
        stateA.doAction(context); // 执行状态 A 的操作

        System.out.println(context.getState().getClass().getSimpleName());

        ConcreteStateB stateB = new ConcreteStateB();
        stateB.doAction(context); // 执行状态 B 的操作

        System.out.println(context.getState().getClass().getSimpleName());
    }
}

4.2 代码分析

  • 状态接口(State):定义了状态的行为,每个具体状态都需要实现该接口。
  • 上下文类(Context):维护当前状态,并委托请求给当前状态的对象。
  • 具体状态类(ConcreteStateA, ConcreteStateB):实现具体的状态逻辑,根据状态改变定义相应的行为。
  • 客户端:通过上下文对象与状态对象进行交互,切换状态并执行对应的行为。

5. 工作流程

  1. 定义状态接口:创建一个接口以定义不同状态的行为。
  2. 实现具体状态类:实现状态接口的类,为每种状态定义对应的处理逻辑。
  3. 创建上下文类:管理状态的切换和状态间的交互,维护当前状态的引用。
  4. 客户端使用:通过上下文对象来调用行为和切换状态。

6. 变种

  1. 多状态模式:使用状态模式来管理复杂的多状态交互。
  2. 状态机模式:结合状态模式和状态机理论,增强对状态转移的控制。

7. 实际应用

状态模式在实际开发中的应用非常广泛,以下是一些典型的应用场景:

  1. 图形用户界面:在 GUI 开发中,组件的不同状态(如按钮的激活、禁用、悬停等)可以通过状态模式来实现。
  2. 游戏开发:角色的不同状态(如行走、跳跃、攻击等),通过状态模式进行状态的管理与转换。
  3. 工作流系统:处理业务过程中的不同状态(如待审批、已审批、拒绝),通过状态模式实现不同的操作。

8. 使用场景

使用状态模式的场景包括:

  • 当对象的行为依赖于其状态,并且需要在运行时根据状态改变行为时。
  • 当需要避免使用大量的条件语句来判断和执行状态转换时。
  • 当状态和行为之间的关系非常紧密,能够出现多种状态的变化时。

9. 优缺点

优点

  1. 简化代码:通过分离状态的行为减少复杂性,避免大量的条件语句。
  2. 灵活性高:便于添加新状态和状态的变化,更易于扩展。
  3. 遵循开闭原则:可以在不修改现有代码的前提下增加新的状态。

缺点

  1. 状态类可能会过多:对于状态非常多的情况,会导致类的数量增加,管理上可能会变得复杂。
  2. 上下文依赖性问题:上下文与具体状态有耦合关系,可能在状态传递上造成影响。

10. 最佳实践

  1. 明确状态与行为:状态和行为之间的关系清晰,状态切换逻辑透明,便于维护。
  2. 管理状态的变化:合理规划状态的切换,确保状态变化不会影响系统的整体逻辑。
  3. 代码重用与扩展:在实现状态模式时,注意在能重用的基础上实现扩展,避免重复代码。

11. 注意事项

  1. 避免过度设计:在状态树不复杂的情况下,使用状态模式可能会导致设计过于复杂。
  2. 合理命名状态类:使用有意义的命名使状态类的职责和作用更加明显。
  3. 关注状态转移的条件:确保状态转移逻辑明确,避免引入混淆。

12. 常见的误区

  • 认为状态模式只适合简单状态:状态模式同样适用复杂系统和业务状态转换。
  • 状态变化会导致内存泄漏:需要注意对状态对象的有效管理,防止因状态切换导致的对象引用问题。
  • 状态模式是单纯使用状态类:状态模式关注的不仅是状态本身,而是规范状态之间的互动及其影响。

13. 常见问题

  • 状态模式的核心组成部分是什么?

    • 包括状态接口、具体状态类、上下文类和客户端。
  • 如何判断使用状态模式的适用性?

    • 当对象的行为依赖于其状态,并且状态转换频繁或复杂时,适合使用状态模式。
  • 状态模式与策略模式的关系是什么?

    • 状态模式主要用于对状态的切换,而策略模式则主要用于对行为的选择。两者在实现方式上有所差异,但可以结合使用。

14. 总结

状态模式是一种行为型设计模式,通过将状态的行为封装在独立的状态类中,使得对象的行为能够在状态变化时进行改变。这种模式不仅提高了系统的灵活性和可维护性,还降低了对象间的耦合度,简化了代码逻辑。在实际开发中,根据具体情况合理使用状态模式,将有助于更好地管理复杂业务逻辑、提升代码的可读性和可扩展性。通过对状态模式的深入理解,开发者可以创建更强大且高效的 Java 应用程序,理清对象之间的关系,并有效针对不同的状态和行为做出合适的反应。

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

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

相关文章

快速幂,错位排序笔记

​ 记一下刚学明白的快速幂和错位排序的原理和代码 快速幂 原理: a^b (a^(b/2)) ^ 2(b为偶数) a^b a*(a^( (b-1)/2))^2(b为奇数) 指数为偶数时…

机器人基础深度学习基础

参考: (1)【具身抓取课程-1】机器人基础 (2)【具身抓取课程-2】深度学习基础 1 机器人基础 从平面二连杆理解机器人学 正运动学:从关节角度到末端执行器位置的一个映射 逆运动学:已知末端位置…

Java语法进阶

目录: Object类、常用APICollection、泛型List、Set、数据结构、CollectionsMap与斗地主案例异常、线程线程、同步等待与唤醒案例、线程池、Lambda表达式File类、递归字节流、字符流缓冲流、转换流、序列化流、Files网络编程 十二、函数式接口Stream流、方法引用 一…

《chatwise:DeepSeek的界面部署》

ChatWise:DeepSeek的界面部署 摘要 本文详细描述了DeepSeek公司针对其核心业务系统进行的界面部署工作。从需求分析到技术实现,再到测试与优化,全面阐述了整个部署过程中的关键步骤和解决方案。通过本文,读者可以深入了解DeepSee…

单节锂电池外部供电自动切换的电路学习

文章目录 前言一、原理分析:①当VBUS处有外部电源输入时②当VBUS处无外部电源输入时 二、器件选择1、二极管2、MOS管3、其他 总结 前言 学习一种广泛应用的锂电池供电自动切换电路 电路存在外部电源时,优先使用外部电源供电,并为电池供电&…

数据结构-堆和PriorityQueue

1.堆&#xff08;Heap&#xff09; 1.1堆的概念 堆是一种非常重要的数据结构&#xff0c;通常被实现为一种特殊的完全二叉树 如果有一个关键码的集合K{k0,k1,k2,...,kn-1}&#xff0c;把它所有的元素按照完全二叉树的顺序存储在一个一维数组中&#xff0c;如果满足ki<k2i…

如何打造一个更友好的网站结构?

在SEO优化中&#xff0c;网站的结构往往被忽略&#xff0c;但它其实是决定谷歌爬虫抓取效率的关键因素之一。一个清晰、逻辑合理的网站结构&#xff0c;不仅能让用户更方便地找到他们需要的信息&#xff0c;还能提升搜索引擎的抓取效率 理想的网站结构应该像一棵树&#xff0c;…

每日Attention学习20——Group Shuffle Attention

模块出处 [MICCAI 24] [link] LB-UNet: A Lightweight Boundary-Assisted UNet for Skin Lesion Segmentation 模块名称 Group Shuffle Attention (GSA) 模块作用 轻量特征学习 模块结构 模块特点 使用分组(Group)卷积降低计算量引入External Attention机制更好的学习特征S…

VUE之组件通信(二)

1、v-model v-model的底层原理&#xff1a;是:value值和input事件的结合 $event到底是啥&#xff1f;啥时候能.target 对于原生事件&#xff0c;$event就是事件对象 &#xff0c;能.target对应自定义事件&#xff0c;$event就是触发事件时&#xff0c;所传递的数据&#xff…

[x86 ubuntu22.04]进入S4失败

目录 1 问题描述 2 解决过程 2.1 查看内核日志 2.2 新建一个交换分区 2.3 指定交换分区的位置 1 问题描述 CPU&#xff1a;G6900E OS&#xff1a;ubuntu22.04 Kernel&#xff1a;6.8.0-49-generic 使用“echo disk > /sys/power/state”命令进入 S4&#xff0c;但是无法…

idea隐藏无关文件

idea隐藏无关文件 如果你想隐藏某些特定类型的文件&#xff08;例如 .log 文件或 .tmp 文件&#xff09;&#xff0c;可以通过以下步骤设置&#xff1a; 打开设置 在菜单栏中选择 File > Settings&#xff08;Windows/Linux&#xff09;或 IntelliJ IDEA > Preference…

文献阅读 250205-Global patterns and drivers of tropical aboveground carbon changes

Global patterns and drivers of tropical aboveground carbon changes 来自 <Global patterns and drivers of tropical aboveground carbon changes | Nature Climate Change> 热带地上碳变化的全球模式和驱动因素 ## Abstract: Tropical terrestrial ecosystems play …

【数据结构】循环链表

循环链表 单链表局限性单向循环链表判断链表是否有环思路code 找到链表入口思路代码结构与逻辑 code 单链表局限性 单链表作为一种基本的数据结构&#xff0c;虽然在很多场景下都非常有用&#xff0c;但它也存在一些局限性&#xff1a; 单向访问&#xff1a;由于每个节点仅包含…

ImGui 学习笔记(二)—— 多视口

在计算机图形学中&#xff0c;视口&#xff08;Viewport&#xff09;是一个可观察的多边形区域。 将物体渲染至图像的过程中&#xff0c;会用两种区域表示。世界坐标窗口是用户所关注的区域&#xff08;即用户想要可视化的东西&#xff09;&#xff0c;坐标系由应用程序确定。…

安装和卸载RabbitMQ

我的飞书:https://rvg7rs2jk1g.feishu.cn/docx/SUWXdDb0UoCV86xP6b3c7qtMn6b 使用Ubuntu环境进行安装 一、安装Erlang 在安装RabbitMQ之前,我们需要先安装Erlang,RabbitMQ需要Erlang的语言支持 #安装Erlang sudo apt-get install erlang 在安装的过程中,会弹出一段信息,此…

Apache HttpClient

HttpClient是apache组织下面的一个用于处理HTTP请求和响应的来源工具&#xff0c;是一个在JDK基础类库是做了更好的封装的类库。 HttpClient 使用了连接池技术来管理 TCP 连接&#xff0c;这有助于提高性能并减少资源消耗。连接池允许 HttpClient 复用已经建立的连接&#xff0…

Golang 并发机制-6:掌握优雅的错误处理艺术

并发编程可能是提高软件系统效率和响应能力的一种强有力的技术。它允许多个工作负载同时运行&#xff0c;充分利用现代多核cpu。然而&#xff0c;巨大的能力带来巨大的责任&#xff0c;良好的错误管理是并发编程的主要任务之一。 并发代码的复杂性 并发编程增加了顺序程序所不…

react使用DatePicker日期选择器

1、引入&#xff1a;npm i day 2、页面引入&#xff1a; import dayjs from dayjs; 3、使用 <DatePicker onChange{onChange} value{datas ? dayjs(datas) : null} /> 4、事件 const onChange (date, dateString) > {setInput(dateString)setDatas(dateString)…

深度学习 Pytorch 基础网络手动搭建与快速实现

为了方便后续练习的展开&#xff0c;我们尝试自己创建一个数据生成器&#xff0c;用于自主生成一些符合某些条件、具备某些特性的数据集。 导入相关的包 # 随机模块 import random# 绘图模块 import matplotlib as mpl import matplotlib.pyplot as plt# 导入numpy import nu…

保姆级教程Docker部署KRaft模式的Kafka官方镜像

目录 一、安装Docker及可视化工具 二、单节点部署 1、创建挂载目录 2、运行Kafka容器 3、Compose运行Kafka容器 4、查看Kafka运行状态 三、集群部署 四、部署可视化工具 1、创建挂载目录 2、运行Kafka-ui容器 3、Compose运行Kafka-ui容器 4、查看Kafka-ui运行状态 …