Java二十三种设计模式-状态模式(20/23)

news2024/9/24 15:28:05

本文深入探讨了状态模式,一种允许对象根据其内部状态变化而改变行为的软件设计模式。文章从定义、组成部分、实现方式、使用场景、优缺点分析、与其他模式的比较,到最佳实践和建议,全面介绍了状态模式的各个方面。通过Java语言的实现示例和实际应用案例,我们展示了状态模式如何提高代码的封装性和可扩展性,同时指出了其可能带来的系统复杂性增加和状态转换管理的挑战。最终,文章旨在帮助读者全面理解状态模式,并在适合的场景中做出明智的设计选择。

 

状态模式:管理状态转换的行为型设计模式

引言

状态模式(State Pattern)是一种行为型设计模式,允许一个对象在其内部状态改变时改变其行为。这种模式通过将每个状态封装为一个单独的类来实现状态的转换。

基础知识,java设计模式总体来说设计模式分为三大类:

(1)创建型模式,共5种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

(2)结构型模式,共7种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

(3)行为型模式,共11种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

 

第一部分:状态模式概述

1.1 定义与用途

状态模式的基本定义

(源于Design Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。

状态模式是一种行为型设计模式,允许一个对象在其内部状态改变时改变其行为。对象看起来似乎修改了其类。

解释为何需要状态模式

  • 封装状态转换:状态模式将所有与特定状态相关的行为封装在单个状态对象中,易于管理和修改。
  • 简化条件逻辑:避免使用大量的条件语句来处理状态转换逻辑,使代码更加清晰。
  • 提高可扩展性:新增状态时,只需添加新的状态类而无需修改现有代码,遵循开闭原则。

1.2 状态模式的组成

上下文(Context)

  • 定义:上下文持有一个状态对象的引用,定义了客户程序与状态对象交互的接口。
  • 职责:维护当前状态,根据当前状态调用相应的行为。

状态接口(State)

  • 定义:状态接口定义了一个或多个方法,用于封装与特定状态相关的行为。
  • 职责:作为所有具体状态类的共同接口。

具体状态(Concrete State)

  • 定义:具体状态类实现状态接口,并根据状态的具体行为来实现这些方法。
  • 职责:定义在特定状态下对象的行为。

角色之间的交互

  • 状态维护:上下文通过持有状态对象的引用来维护当前状态。
  • 状态转换:当对象的状态需要改变时,上下文会替换状态对象,从而改变行为。
  • 行为执行:上下文通过委托给当前状态对象来执行相关的行为。

状态模式通过将状态相关的逻辑封装在具体的状态类中,使得状态转换逻辑变得清晰和易于管理。在下一部分中,我们将通过Java代码示例来展示状态模式的具体实现。

第二部分:状态模式的实现

2.1 Java实现示例

以下是使用Java语言实现状态模式的代码示例。假设我们有一个简单的文本编辑器,它支持两种状态:正常模式和加粗模式。

// 状态接口
interface State {
    void handleRequest(TextEditor editor);
}

// 具体状态:正常模式
class NormalMode implements State {
    @Override
    public void handleRequest(TextEditor editor) {
        System.out.println("Text is in normal mode.");
        // 其他正常模式下的行为
    }
}

// 具体状态:加粗模式
class BoldMode implements State {
    @Override
    public void handleRequest(TextEditor editor) {
        System.out.println("Text is in bold mode.");
        editor.setMode(new NormalMode()); // 切换回正常模式
    }
}

// 上下文
class TextEditor {
    private State state;

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

    public void type(String message) {
        state.handleRequest(this);
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        TextEditor editor = new TextEditor();
        editor.setMode(new NormalMode());
        editor.type("Initial text in normal mode.");

        editor.setMode(new BoldMode());
        editor.type("Text after applying bold.");
    }
}

2.2 状态模式中的角色和职责

上下文(Context)

  • 职责:维护当前的状态对象,根据当前状态调用相应的行为。
  • 交互:客户端通过上下文与状态对象交互,上下文将请求委托给当前状态对象。

状态接口(State)

  • 职责:定义所有具体状态类必须实现的接口,通常包含处理请求的方法。
  • 交互:作为上下文与具体状态之间的桥梁,确保状态的一致性和可替换性。

具体状态(Concrete State)

  • 职责:实现状态接口中定义的方法,提供具体的行为实现。
  • 交互:响应上下文的请求,执行与状态相关的行为,并在需要时触发状态转换。

角色之间的相互作用

  • 状态设置:客户端通过上下文设置当前状态。
  • 请求处理:上下文接收到请求后,委托给当前状态对象处理。
  • 状态转换:具体状态对象在处理请求时,可以根据逻辑需要切换到另一个状态。

状态模式通过将状态相关的逻辑封装在具体的状态类中,实现了状态转换的逻辑与状态行为的逻辑分离,使得状态转换更加灵活和易于管理。在下一部分中,我们将探讨状态模式的使用场景。

第三部分:状态模式的使用场景

3.1 需要表示状态的对象

在软件开发中,经常会遇到需要表示对象状态的情况,尤其是在这些状态会影响对象行为的场景中。

讨论在需要表示对象状态时,状态模式的应用:

  • 封装状态行为:状态模式允许将与特定状态相关的行为封装在单独的状态类中,使得状态的管理更加清晰。
  • 简化对象行为:通过状态模式,对象不需要包含所有可能状态的行为,而是根据当前状态委托给对应的状态对象。

应用实例:

  • 用户会话管理:在用户会话中,状态可能包括登录、注销、锁定等,每个状态都有不同的行为。
  • 订单处理系统:订单的状态可能包括未支付、已支付、已发货、已完成等,每个状态都对应不同的操作。

3.2 状态转换逻辑复杂

当对象的状态转换逻辑变得复杂时,状态模式可以提供一种清晰和灵活的方式来管理这些转换。

分析在状态转换逻辑复杂时,状态模式的优势:

  • 集中管理状态转换:状态模式将状态转换逻辑集中管理,避免了分散在多个地方的重复和错误。
  • 易于添加新状态:当需要添加新的状态或转换时,只需添加新的状态类,而无需修改现有代码,符合开闭原则。
  • 提高可维护性:状态模式使得状态转换逻辑的维护和理解变得更加容易,因为每个状态都是独立的类。

应用实例:

  • 工作流引擎:在工作流引擎中,状态模式可以用来管理任务的不同阶段,如待审核、审核中、已完成等。
  • 游戏角色状态:在游戏开发中,角色可能有不同的状态,如站立、行走、奔跑、受伤等,状态模式可以管理这些状态及其转换。

状态模式通过将状态和行为封装在独立的对象中,为管理对象的状态和状态转换提供了一种有效的方法。在实际开发中,根据具体需求和场景选择是否使用状态模式是非常重要的。在下一部分中,我们将讨论状态模式的优点与缺点。

第四部分:状态模式的优点与缺点

4.1 优点

降低耦合度

  • 解耦状态与行为:状态模式将状态相关的逻辑从对象本身解耦出来,封装在不同的状态类中。

提高可扩展性

  • 新状态的添加:新增状态时,只需添加新的状态类,无需修改现有代码,易于扩展。

增强可维护性

  • 状态逻辑集中管理:所有状态的逻辑都封装在各自的状态类中,便于集中管理和维护。

提供一致的接口

  • 统一的上下文接口:上下文类提供了统一的接口来访问状态相关的行为,简化了客户端代码。

支持状态转换的封装

  • 封装转换逻辑:状态转换的逻辑可以在状态类内部封装,使得状态转换更加灵活和可控。

4.2 缺点

增加系统复杂性

  • 类的数量增加:状态模式可能会增加系统中类的数量,每个状态都需要一个单独的状态类。

状态类管理困难

  • 状态类增多:随着状态数量的增加,状态类的管理可能变得复杂和难以追踪。

状态转换的控制

  • 转换逻辑集中:所有状态转换逻辑都集中在上下文或状态类中,可能使得状态转换难以控制和理解。

状态依赖管理

  • 状态间的依赖:如果状态之间存在依赖关系,状态模式可能会导致这些依赖关系难以管理和维护。

性能考虑

  • 性能开销:在某些情况下,状态模式可能会引入额外的性能开销,尤其是在状态转换频繁的情况下。

状态模式通过将状态和行为封装在独立的对象中,为管理对象的状态和状态转换提供了一种有效的方法。然而,合理使用状态模式并避免其缺点是至关重要的。了解其优点和缺点可以帮助开发者根据具体需求和场景选择最合适的设计模式。在实际开发中,应根据具体情况灵活运用状态模式,以达到最佳的设计效果。

第五部分:状态模式与其他模式的比较

5.1 与策略模式的比较

策略模式

  • 定义:策略模式定义了一系列的算法,并将每一个算法封装起来,使它们可以互换。
  • 特点:策略模式关注于算法的封装和替换,通常用于多种算法或行为的动态选择。

状态模式

  • 定义:状态模式允许一个对象在其内部状态改变时改变其行为,看起来像是改变了其类。
  • 特点:状态模式关注于对象状态的封装和状态转换,通常用于对象状态较多且状态相关行为有明显差异的情况。

对比

  • 封装内容:策略模式封装的是不同的算法或行为,状态模式封装的是与特定状态相关的行为。
  • 使用场景:策略模式适用于需要根据不同条件选择不同算法的场景,状态模式适用于需要根据不同状态执行不同行为的场景。

5.2 与命令模式的对比

命令模式

  • 定义:命令模式将请求或操作封装为一个对象,允许用户使用不同的请求对客户进行参数化。
  • 特点:命令模式关注于请求的封装和排队,通常用于支持撤销和重做操作。

状态模式

  • 定义:如前所述,状态模式关注于对象状态的封装和状态转换。

对比

  • 请求处理:命令模式通过命令对象来处理请求,状态模式通过状态对象来处理与状态相关的行为。
  • 目的:命令模式用于将请求作为对象进行处理,支持撤销和重做,状态模式用于根据对象的状态改变其行为。

状态模式和策略模式、命令模式都提供了处理对象行为的不同方法。每种模式都有其独特的用途和优势,选择使用哪种模式取决于具体的设计需求和场景。在下一部分中,我们将提供状态模式的最佳实践和建议。

 

第六部分:状态模式的最佳实践和建议

6.1 最佳实践

保持状态转换的清晰性

  • 明确转换条件:确保状态转换的条件和逻辑是清晰和明确的,避免隐晦或复杂的转换逻辑。

定义清晰的接口

  • 统一接口:确保所有状态类都遵循统一的状态接口,使得状态转换和行为调用标准化。

状态类的单一职责

  • 单一职责原则:每个状态类应该只负责一种状态的行为,遵循单一职责原则。

避免过度使用状态模式

  • 合理使用:仅在对象的状态确实影响其行为时使用状态模式,避免过度设计。

提供状态转换的反馈

  • 反馈机制:在状态转换时提供清晰的反馈,让调用者了解转换的结果。

考虑使用状态模式框架

  • 框架支持:考虑使用现有的状态模式框架或库,以简化实现和维护工作。

6.2 避免滥用

避免过度复杂的状态类

  • 简化设计:避免设计过于复杂的状态类,这可能导致系统难以理解和维护。

避免状态模式的过度泛化

  • 具体问题具体分析:只在真正需要根据状态改变行为的场景中使用状态模式,避免泛化到所有问题。

避免忽略状态转换的触发条件

  • 明确触发条件:确保状态转换的触发条件是明确和合理的,避免无序或意外的转换。

6.3 替代方案

使用状态机图

  • 图形化表示:对于复杂的状态转换逻辑,使用状态机图来图形化表示和设计可能更为直观。

使用查表法

  • 查找表:在某些情况下,使用查找表来确定状态转换可能更为简单和高效。

结合策略模式

  • 策略与状态结合:在状态类中使用策略模式来进一步封装行为,使得状态类更加专注于状态管理。

使用面向对象的编程特性

  • 封装与多态:利用面向对象编程的封装和多态特性来简化状态的表示和转换。

状态模式是一种强大的设计模式,适用于对象状态影响其行为的场景。合理使用状态模式并避免其缺点对于构建清晰、可维护的系统至关重要。了解其替代方案可以帮助开发者根据具体需求和场景选择最合适的设计模式。在实际开发中,应根据具体情况灵活运用状态模式,以达到最佳的设计效果。

结语

状态模式通过将状态封装为对象,为对象的状态转换提供了一种灵活且可维护的解决方案。通过本文的深入分析,希望读者能够对状态模式有更全面的理解,并在实际开发中做出合理的设计选择。


博主还写了其他Java设计模式关联文章,请各位大佬批评指正:

(一)创建型模式(5种):

Java二十三种设计模式-单例模式(1/23)

Java二十三种设计模式-工厂方法模式(2/23)

Java二十三种设计模式-抽象工厂模式(3/23)

Java二十三种设计模式-建造者模式(4/23)

Java二十三种设计模式-原型模式(5/23)

(二)结构型模式(7种): 

Java二十三种设计模式-适配器模式(6/23)

Java二十三种设计模式-装饰器模式(7/23)

Java二十三种设计模式-代理模式(8/23)

Java二十三种设计模式-外观模式(9/23)

Java二十三种设计模式-桥接模式(10/23)

Java二十三种设计模式-组合模式(11/23)

Java二十三种设计模式-享元模式(12/23)

 (三)行为型模式(11种): 

Java二十三种设计模式-策略模式(13/23)

Java二十三种设计模式-模板方法模式(14/23)

Java二十三种设计模式-观察者模式(15/23)

Java二十三种设计模式-迭代子模式(16/23)

Java二十三种设计模式-责任链模式(17/23)

Java二十三种设计模式-命令模式(18/23)

Java二十三种设计模式-备忘录模式(19/23)

欲知后事如何,且看下文分解......

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

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

相关文章

2024前端面试题-篇章一(个人向)

1.vue2生命周期(省略) 2.vue3生命周期(省略) 3.vue2页面生命周期与组件生命周期执行顺序: 一般是 页面先创建,然后准备再准备挂载,挂载的时候发现有组件再执行组件的生命周期,组件…

数字影像技术是如何改变我们看待世界的方式呢?

在当今的科技时代,数字影像技术正以惊人的速度改变着我们的生活和视觉体验。那么,什么是数字影像技术呢? 数字影像技术是指通过数字化手段对图像和视频进行获取、处理、存储、传输和展示的一系列技术。 它利用各种数字设备,如数…

msf+proxychains组合搭建socks5隧道 | 内网穿透

实验环境 网络拓扑: kali: VMnet1(公网)192.168.52.134 win10: VMnet1(公网)192.168.52.135VMnet2(内网)192.168.72.133 win2008: VMnet2&#xff08…

【数据结构初阶】二叉树--基本概念

hello! 目录 一、树 1.1 树的概念和结构 1.2 树的相关术语 1.3 树的表示 1.4 树形结构实际应用场景 二、二叉树 2.1 概念和结构 2.2 特殊的二叉树 2.2.1 满二叉树 2.2.2 完全二叉树 2.3 二叉树的存储结构 2.3.1 顺序结构 2.3.2 链式结构 …

转行到大模型,完整版攻略从大模型零基础到大模型精通,我是这样过来的

在当今这个日新月异的时代,技术的更新迭代速度远超我们的想象。对于那些渴望在职业生涯中寻求新挑战的人来说,转向人工智能领域,尤其是投身于大规模语言模型的研究与开发,无疑是一个充满机遇的选择。本文将为您揭示如何从零开始&a…

阿里十万卡训练集群 网络拓扑架构和优势 Alibaba HPN: A Data Center Network for Large Language Model Training

本博客的视频教程在这: 2.2阿里十万卡集群 网络拓扑架构和优势 Alibaba HPN: A Data Center Network for Large Language Model_哔哩哔哩_bilibili 一、大模型训练的核心问题 1.1 流量模式的问题 大语言模型训练的流量模式问题可参考这个: ECMP等价…

Linux 服务器下非root用户安装CUDA完整流程(多次踩雷经验总结)

参考博客: linux下安装cuda和cudnn(非root权限)_cuda下载安装 远程服务器 linux-CSDN博客 Linux下非root用户安装CUDA_linux下cuda-toolkit-archive-CSDN博客 非root用户安装cuda10.1,以及CUDA不同版本间切换_非root用户.run文…

已解决centos7 yum报错:cannot find a valid baseurl for repo:base/7/x86_64的解决方案

出现cannot find a valid baseurl for repo:base/7/x86_64错误通常是由于YUM仓库源无法找到或无法访问,导致YUM无法正常工作。这种情况常见于CentOS 7系统。解决这个问题需要检查几个方面,如网络连接、DNS设置和YUM仓库源配置。 🧑 博主简介&…

aspose-words中插入附件及遇到的问题

aspose-words版本:21.1 java:1.8 目标: 前端使用tinymce编辑一段内容,后端使用aspose-words将html转为word,并将html中的附件转换为word中的附件。 形如: 实现方案: 使用正则表达式找出需要替…

setData的 Qt::CheckStateRole是model中checkbox的状态(选中否)

checkbox的状态 bool MissionModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (role Qt::CheckStateRole && col 3 ) { } }

【嵌入式裸机开发】基于stm32的照相机(OV7670摄像头、STM32、TFTLCD)

基于STM32的照相机 准备工作最终效果一、下位机1、主函数2、OV7670初始化 二、上位机1、控制拍照2、接收图片数据 准备工作 一、硬件及片上资源: 1,串口1(波特率:921600,PA9/PA10通过usb转ttl连接电脑,或者其他方法)上传图片数据至上位机 2,串口2(波特率:115200,PA…

Opencv学习-直方图应用

1. 直方图均衡化 如果一个图像的直方图都集中在一个区域,那么整体图像的对比度比较小,不便于图像中纹理的识别。例如,如果相邻的两个像素灰度值分别是 120 和 121 ,那么仅凭肉眼是无法区别出来的。同时,如果图像中所…

音频提取软件分享:6款好用音频提取工具推荐

在现代数字媒体中,音频提取已经成为一项至关重要的技能。无论你是视频创作者、播客主持人,还是音乐爱好者,从视频、电影或其他多媒体文件中提取音频,都是一项非常有用的操作。 本文将围绕音频提取,介绍这项技术的应用、…

一篇文章带你实现大模型及RAG入门---小白速进

项目概述:随着人工智能技术的飞速发展,大模型(Large Models)和检索增强型生成(Retrieval-Augmented Generation, RAG)已成为自然语言处理(NLP)领域的热点。大模型以其强大的理解和生…

Java二十三种设计模式-责任链模式(17/23)

责任链模式:实现请求处理的灵活流转 引言 在这篇博客中,我们深入探讨了责任链模式的精髓,从其定义和用途到实现方法,再到使用场景、优缺点、与其他模式的比较,以及最佳实践和替代方案,旨在指导开发者如何…

力扣第 411 场周赛题解

3258. 统计满足 K 约束的子字符串数量 I 给你一个 二进制 字符串 s 和一个整数 k。 如果一个 二进制字符串 满足以下任一条件,则认为该字符串满足 k 约束: 字符串中 0 的数量最多为 k。字符串中 1 的数量最多为 k。 返回一个整数,表示 s …

系统编程-进程初步1

5 进程初步 一、认识进程 -- 进程Process是指计算机中已运行的程序,是系统进行资源分配和调度的基本单位,是操作系统结构的基础 -- 程序运行起来就是一个进程 进程存在于运行内存中程序存在于硬盘中 -- windows下查看进程使用任务管理器进行查看 1…

EXCEL——Vlookup17个高级用法

大纲 一、基本语法 1、参数详解 二、入门篇 1、单条件查找 2、屏蔽查找返回的错误值 三、进阶篇 1、反向查找 2、包含查找 3、区间查找 4、含通配符查找 5、多列查找 6、多区域查找 四、高级篇 1、多条件查找 2、合并单元格查找 3、带合并单元格的多条件查找 …

轻松玩转音频剪辑:推荐四大必备工具!

在这个多媒体时代,音频剪辑技能变得至关重要。无论是制作短视频、音频节目,还是音乐创作,一款得心应手的音频剪辑工具都能让你事半功倍。今天,我们将推荐几款热门音频剪辑工具,助你轻松玩转声音世界 福昕音频剪辑 链…

【数学建模】趣味数学模型——等额还款数学模型

问题 在银行贷款中,通常采用等额还款。假定银行贷款的年利率为 p,贷款 k 元,分 m 年采用每月等额还款方式还清。问每月还款多少钱?总共还的钱是多少?每月还款中还本金和利息各是多少元? 如果考虑每月等额…