【设计模式】行为型-状态模式

在变幻的时光中,状态如诗篇般细腻流转。

文章目录

  • 一、可调节的灯光
  • 二、状态模式
  • 三、状态模式的核心组件
  • 四、运用状态模式
  • 五、状态模式的应用场景
  • 六、小结
  • 推荐阅读

一、可调节的灯光

场景假设:我们有一个电灯,它可以被打开和关闭。用户可以通过一个开关来改变电灯的状态。

/*** 表示可以开关的灯的类。*/
public class Light {private String state; // 灯的当前状态,可能是"ON"或者"OFF"/*** 构造方法,初始化灯的状态为"OFF"。*/public Light() {this.state = "OFF";}/*** 开关灯的状态。* 如果灯当前为"OFF",则将其改为"ON"并打印"灯已打开"。* 如果灯当前为"ON",则将其改为"OFF"并打印"灯已关闭"。*/public void switchState() {if ("OFF".equals(state)) {state = "ON";System.out.println("灯已打开");} else {state = "OFF";System.out.println("灯已关闭");}}
}

上面的代码虽然能够实现需求,因为只有两种状态。但是,如果电灯有更多的状态,比如“调暗”、“调亮”、“闪烁”等,那么 switchState 方法就会变得非常复杂,充满了 if-else 语句。这将使代码难以阅读和维护。

二、状态模式

状态模式(State Pattern)是一种行为型设计模式,它允许对象在其内部状态发生改变时改变其行为,使其看起来像是改变了其类。状态模式的关键思想是将对象的行为封装在不同的状态对象中,并且在状态转换时可以动态地改变对象的行为。

三、状态模式的核心组件

状态模式的核心组件包括以下几个角色:

  1. Context(上下文):上下文是拥有状态的对象。它定义了客户端感兴趣的接口,并且维护一个当前状态对象,这个状态对象定义了当前的状态和相应的行为。Context 可以通过状态对象来改变它的行为。
  2. State(状态):状态是一个接口或者抽象类,它封装了与 Context 的一个特定状态相关的行为。在 State 接口或者抽象类中定义了所有具体状态类所共享的方法,这些方法的实现将依赖于当前状态。通常,这些方法处理与状态相关的操作,如请求或者事件。
  3. ConcreteState(具体状态):具体状态类实现了 State 接口或者继承了 State 抽象类。每个具体状态类实现了与 Context 的一个状态相关的行为。例如,在电梯系统中,可能会有开门状态、关门状态、运行状态和停止状态等具体状态类。

在这里插入图片描述

这个类图展示了状态模式的核心组成部分:

  • State 接口定义了 doAction(Context) 方法,表示所有具体状态类(OpenState 和 CloseState)需要实现的方法。
  • OpenState 和 CloseState 类分别实现了 State 接口,并实现了 doAction(Context) 方法来处理具体的状态操作。
  • Context 类包含一个状态接口类型的私有成员变量 state,通过 setState(State) 方法设置当前的状态,并通过 request() 方法执行当前状态的动作。

四、运用状态模式

场景假设:我们有一个电灯,它可以被打开和关闭。用户可以通过一个开关来改变电灯的状态。电灯有更多的状态,比如“调暗”、“调亮”、“闪烁”等。

  1. 定义状态接口:首先,我们需要定义一个状态接口,该接口声明了所有具体状态类需要实现的方法。在我们的例子中,我们可以定义一个 LightState 接口,该接口有一个 switchState 方法。

    // 定义状态接口
    public interface LightState {// 声明改变状态的方法,接收一个 Light 对象作为参数void switchState(Light light);
    }
    
  2. 创建具体状态类:然后,我们需要为每种状态创建一个具体的状态类。这些类需要实现状态接口,并实现接口中声明的方法。在我们的例子中,我们可以创建 OnState 和 OffState 类。

    // 创建具体状态类:打开状态
    public class OnState implements LightState {@Overridepublic void switchState(Light light) {// 改变 Light 对象的状态为 DimStatelight.setState(new DimState());System.out.println("Light is dimmed");}
    }// 创建具体状态类:关闭状态
    public class OffState implements LightState {@Overridepublic void switchState(Light light) {// 改变 Light 对象的状态为 OnStatelight.setState(new OnState());System.out.println("Light is turned ON");}
    }// 创建具体状态类:调暗状态
    public class DimState implements LightState {@Overridepublic void switchState(Light light) {// 改变 Light 对象的状态为 BlinkStatelight.setState(new BlinkState());System.out.println("Light is blinking");}
    }// 创建具体状态类:闪烁状态
    public class BlinkState implements LightState {@Overridepublic void switchState(Light light) {// 改变 Light 对象的状态为 OffStatelight.setState(new OffState());System.out.println("Light is turned OFF");}
    }
    
  3. 在上下文类中使用状态:最后,我们需要在上下文类中使用这些状态。上下文类维护一个对状态对象的引用,该引用可以在运行时更改。在我们的例子中,Light 类就是上下文类。

    // 创建上下文类:电灯
    public class Light {// Light 对象维护一个对状态对象的引用private LightState state;public Light() {// 初始状态为 OffStatethis.state = new OffState();}// 设置 Light 对象的状态public void setState(LightState state) {this.state = state;}// 切换 Light 对象的状态public void switchState() {state.switchState(this);}
    }
    
  4. 客户端:通过客户端测试

    public class Client {public static void main(String[] args) {// 创建一个 Light 对象Light light = new Light();// 切换 Light 对象的状态light.switchState(); // 打开电灯light.switchState(); // 调暗电灯light.switchState(); // 电灯开始闪烁light.switchState(); // 关闭电灯}
    }
    

五、状态模式的应用场景

状态模式在许多场景中都非常有用,特别是当一个对象的行为取决于其状态,并且它必须在运行时根据状态改变其行为时。以下是一些常见的应用场景:

  1. 用户界面(UI):在许多用户界面中,元素的行为会根据其状态(如禁用、选中、悬停等)而改变。状态模式可以帮助我们管理这些状态,并使状态转换的逻辑更加清晰。
  2. 游戏开发:在游戏开发中,角色的行为通常会根据其状态(如站立、跑动、跳跃、攻击等)而改变。使用状态模式,我们可以为每种状态创建一个状态类,使得代码更易于理解和维护。
  3. 工作流引擎:在工作流引擎中,任务的行为会根据其状态(如新建、进行中、已完成等)而改变。状态模式可以帮助我们管理这些状态,并使状态转换的逻辑更加清晰。
  4. 网络连接:网络连接的行为会根据其状态(如打开、关闭、等待等)而改变。状态模式可以帮助我们管理这些状态,并使状态转换的逻辑更加清晰。

六、小结

状态模式是一种优秀的设计模式,适用于那些对象行为会随着内部状态变化而变化的情况。它通过将对象的状态和行为分离,使得系统更加灵活、易于理解和扩展。

推荐阅读

  1. 深入探究 Spring Boot Starter:从概念到实践
  2. 深入理解 Java 中的 volatile 关键字
  3. OAuth 2.0:现代应用程序的授权标准
  4. Spring 三级缓存
  5. 深入了解 MyBatis 插件:定制化你的持久层框架

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大模型与机器人精彩碰撞-7月5日晚上八点不见不散!

在瞬息万变的科技时代,新兴人工智能和机器人技术的结合正在引领新一轮的创新浪潮。你是否想成为未来科技的领航者?你是否想了解最前沿的AI与机器人技术?行麦科技重磅推出的“AIGC时代的生存法则”AI系列课,将为你揭开大模型与机器…

redis学习(001 介绍)

黑马程序员Redis入门到实战教程,深度透析redis底层原理redis分布式锁企业解决方案黑马点评实战项目 总时长 42:48:00 共175P 此文章包含第1p-第p4的内容 文章目录 介绍差异对比事务区别 认识redis 介绍 两种键值对方式对比 差异对比 事务区别 认识redis

Paimon 在汽车之家的业务实践

汽车之家基于Paimon的实践 摘要:本文分享自汽车之家的王刚、范文、李乾⽼师。介绍了汽车之家基于 Paimon 的一些实践,和一些背景。内容主要为以下四部分: 一、背景 二、业务实践 三、paimon 优化实践 四、未来规划 一、背景 在使用Paimon之前…

Java---Mybatis详解二

雄鹰展翅凌空飞, 大江奔流不回头。 壮志未酬心未老, 豪情万丈任遨游。 巍巍高山攀顶峰, 滔滔黄河入海流。 风云变幻凭君舞, 踏遍天涯尽逍遥。 目录 一,环境准备 二,删除 三,删除(预编译SQL) 为什…

无法定位程序输入点Z9 qt assertPKcS0i于动态链接库F:\code\projects\06_algorithm\main.exe

解决方法: 这个报错,是因为程序在运行时没要找到所需的dll库,如果把这个程序方法中对应库的目录下执行,则可正常执行。即使将图中mingw_64\bin 环境变量上移到msvc2022_64\bin 之前也不可以。 最终的解决方法是在makefile中设置环…

RealMAN:大规模真实录制且经过注释的麦克风阵列数据集

在深度学习驱动的多通道语音增强和声源定位系统的开发中,由于缺乏大规模的真实录制数据集,这些系统的训练在很大程度上依赖于房间脉冲响应(RIR)和多通道扩散噪声的模拟。然而,模拟数据和真实世界数据之间存在的声学失配…

QStringListModel 绑定到QListView

1.QStringListModel 绑定到listView,从而实现MV模型视图 2.通过QStringListModel的新增、删除、插入、上下移动,listView来展示出来 3.下移动一行,传入curRow2 的个人理解 布局 .h声明 private:QStringList m_strList;QStringListModel *m_m…

[译]Reactjs性能篇

英文有限,技术一般,海涵海涵,由于不是翻译出身,所以存在大量的瞎胡乱翻译的情况,信不过我的,请看原文~~ 原文地址:https://facebook.github.io/react/docs/advanced-per…

Servlet_Web小结

1.web开发概述 什么是服务器? 解释一:服务器就是一款软件,可以向其发送请求,服务器会做出一个响应. 可以在服务器中部署文件,让他人访问 解释二:也可以把运行服务器软件的计算机也可以称为服务器。 web开发: 指的是从网页中向后…

Android LayoutInflater 深度解析

在 Android 开发中,LayoutInflater 是一个非常重要的工具。它允许我们从 XML 布局文件中动态地创建 View 对象,从而使得 UI 的创建和管理更加灵活。本文将深入解析 android.view.LayoutInflater,包括它的基本用法、常见问题以及高级用法。 什…

idea xml ctrl+/ 注释格式不对齐

处理前 处理后 解决办法 取消这两个勾选

【UE5.3】笔记6-创建可自由控制Pawn类

搭建场景 搭建一个场景:包含地板、围墙。可以根据喜好加一些自发光的效果。 增加食物 创建食物蓝图类,在场景里放置一些食物以供我们player去吃掉获取分值。 创建可控制的layer 我们先右键创建一个蓝图继承自pawn类,起名BP_Player&#xf…

深度学习之半监督学习:一文梳理目标检测中的半监督学习策略

什么是半监督目标检测? 传统机器学习根据训练数据集中的标注情况,有着不同的场景,主要包括:监督学习、弱监督学习、弱半监督学习、半监督学习。由于目标检测任务的特殊性,在介绍半监督目标检测方法之前,我…

视频融合共享平台LntonCVS统一视频接入平台智慧安防应用方案

安防视频监控平台LntonCVS是一款拥有强大拓展性和灵活部署能力的综合管理平台。它支持多种主流标准协议,包括国标GB28181、RTSP/Onvif、RTMP等,同时兼容各厂家的私有协议和SDK,如海康Ehome、海大宇等。LntonCVS不仅具备传统安防视频监控功能&…

PHP电商系统开发指南最佳实践

电子商务系统开发的最佳实践包括:数据库设计:选择适合关系型数据库,优化数据结构,考虑表分区;安全:加密数据,防止 sql 注入,处理会话管理;用户界面:遵循 ux 原…

mysql-sql-第十四周

学习目标: sql 学习内容: 40.查询学过「哈哈」老师授课的同学的信息 Select * from students left join score on students.stunmscore.stunm where counm (select counm from teacher left join course on teacher.teanmcourse.teanm where teache…

【深度学习】Transformer

李宏毅深度学习笔记 https://blog.csdn.net/Tink1995/article/details/105080033 https://blog.csdn.net/leonardotu/article/details/135726696 https://blog.csdn.net/u012856866/article/details/129790077 Transformer 是一个基于自注意力的序列到序列模型,与基…

伺服调试三环讲解

在伺服调试过程中,有些项目要求不高,采用伺服自整定就可以调试好伺服,但有些项目对伺服有着比较高的要求,于是需要采取手动调试伺服参数,下面就介绍一下伺服三环参数的调试的方法。 三环指:电流环、速度环、位置环 带宽关系:电流环带宽>速度环带宽>位置环带宽 三环控…

C语言单链表的算法之插入节点

一:访问各个节点中的数据 (1)访问链表中的各个节点的有效数据,这个访问必须注意不能使用p、p1、p2,而只能使用phead (2)只能用头指针不能用各个节点自己的指针。因为在实际当中我们保存链表的时…

偏微分方程笔记

极小位能原理: C 2 C^2 C2 是一个集合符号,表示所有二阶连续可微函数的集合 弱导数 C 2 C^2 C2 是一个集合符号,表示所有二阶连续可微函数的集合。 C 0 ∞ ( I ) C^{\infty}_0(I) C0∞​(I)表示于 I I I上无穷可微,且在端点a&…