状态模式:灵活应对对象行为变化,实现状态驱动的智能设计

文章目录

  • **一、技术背景与应用场景**
    • **为何使用状态模式?**
    • **典型应用场景包括但不限于:**
  • **二、状态模式定义与结构**
  • **三、使用步骤举例**
  • **四、优缺点分析**
  • **总结**

一、技术背景与应用场景

状态模式是一种行为设计模式,用于处理一个对象在其内部状态改变时,其行为也随之发生相应变化的情况。例如,在ATM机中,用户操作(取款、存款、查询等)会引发系统状态的变化和对应的操作;游戏角色根据所处状态(行走、奔跑、战斗)执行不同的动作。

为何使用状态模式?

  1. 减少条件分支:通过将状态与相关行为封装为独立类,可显著降低业务逻辑中的嵌套或分支条件判断,提高代码可读性和维护性。
  2. 易于扩展新状态:当需要新增状态或修改状态行为时,只需创建新的状态类或调整现有状态类即可,不影响原有系统的整体结构。
  3. 职责明确:遵循单一职责原则,状态管理与状态相关的操作分离,使得各部分职责更加清晰。

典型应用场景包括但不限于:

  • 游戏开发:游戏角色的不同状态及其关联行为。
  • 设备控制:家电设备的各种工作模式切换及其响应操作。
  • 订单系统:订单流程中的不同状态(待支付、已支付、已发货、已完成等)及相应的操作处理。

二、状态模式定义与结构

状态模式包含四个核心组成部分:

在这里插入图片描述

  1. 环境角色(Context):持有当前状态,并将与状态相关的请求委托给当前状态对象来处理。
  2. 抽象状态角色(State):定义所有具体状态类需要实现的接口,通常包含一个或多个方法,用于处理来自环境角色的方法调用。
  3. 具体状态角色(Concrete State):实现了抽象状态角色声明的接口,每个具体状态对应一种特定的行为。
  4. 状态转移:在某个具体状态对象执行对应处理行为时,它可能会改变环境角色的状态引用,指向另一个具体状态对象。

三、使用步骤举例

模拟了一个简单的电商订单系统,这个系统通过状态模式来处理订单从创建到完成或取消的整个生命周期中的不同状态和操作。

  1. 抽象状态角色(OrderState):定义了所有具体状态类需要实现的方法接口,包括place()pay()ship()cancel()等。

    // 抽象状态角色
    public abstract class OrderState {protected Order order;public void setOrder(Order order) {this.order = order;}// 抽象方法,由具体状态类实现public abstract void place();   //下单public abstract void pay();     //支付public abstract void ship();    //发货public abstract void cancel();    //取消订单
    }
    
  2. 具体状态角色

    • CreatedState:代表订单刚创建的状态,在此状态下可以进行下单和取消操作,当调用place()时只是打印提示信息,而调用cancel()会将订单状态转换为CancelledState

      // 具体状态角色
      public class CreatedState extends OrderState {@Overridepublic void place() {System.out.println("订单已创建,等待支付");}@Overridepublic void pay() {System.out.println("订单已支付~");// 转换状态至“已支付”状态order.setState(new PaidState());}@Overridepublic void ship() {System.out.println("请先完成支付才能发货");}@Overridepublic void cancel() {System.out.println("订单已取消");// 设置订单为已取消状态order.setState(new CancelledState());}
      }
      
    • PaidState:代表订单已支付的状态,在此状态下无法再次下单或支付,但可以进行发货和取消操作。发货时会将订单状态转换为ShippedState,取消则转换为CancelledState

      public class PaidState extends OrderState {@Overridepublic void place() {System.out.println("请勿重复下单");}@Overridepublic void pay() {System.out.println("订单已支付,无需再次支付");}@Overridepublic void ship() {System.out.println("订单开始发货...");// 转换状态至“已发货”状态order.setState(new ShippedState());}@Overridepublic void cancel() {System.out.println("正在申请退款...");// 设置订单为已取消状态order.setState(new CancelledState());}
      }
      
    • ShippedState:代表订单已发货的状态,在此状态下仅能查看状态,不能执行其他操作。

      public class ShippedState extends OrderState {@Overridepublic void place() {System.out.println("请勿重复下单");}@Overridepublic void pay() {System.out.println("订单已支付,无需再次支付");}@Overridepublic void ship() {System.out.println("订单已发货,无需再次发货");}@Overridepublic void cancel() {System.out.println("您已无法取消已发货的订单");}
      }
      
    • CancelledState:代表订单已取消的状态,同样只能查看状态,不能执行其他操作。

      public class CancelledState extends OrderState {@Overridepublic void place() {System.out.println("您的订单已取消,请重新下单");}@Overridepublic void pay() {System.out.println("该订单已取消,无法进行支付");}@Overridepublic void ship() {System.out.println("该订单已取消,无法发货");}@Overridepublic void cancel() {System.out.println("订单已处于取消状态");}
      }
      
  3. 环境角色(Order):持有当前订单状态,并提供与订单状态相关联的操作方法(如place()pay()等)。当调用这些方法时,实际上是委托给当前持有的状态对象去执行相应的行为。

    // 环境角色
    public class Order {private OrderState state;public void setState(OrderState state) {this.state = state;state.setOrder(this);}public void place() {state.place();}public void pay() {state.pay();}public void ship() {state.ship();}public void cancel() {state.cancel();}
    }
    
  4. 应用端示例(OrderStateMachineDemo)
    创建一个新订单实例,初始状态下是CreatedState。然后按照实际业务流程调用place()pay()ship()cancel()方法,根据不同的状态,订单的行为会有不同的响应,并可能触发状态的转换。

// 应用端示例
public class OrderStateMachineDemo {public static void main(String[] args) {Order order = new Order();order.setState(new CreatedState()); // 初始状态为“已创建”order.place();  // 根据状态进行操作order.pay();order.ship();order.cancel();}
}

测试结果

在这里插入图片描述


四、优缺点分析

状态模式的优点在于:

  • 模块化状态行为:各状态行为被划分到各自的具体状态类中,便于理解和维护。
  • 增强灵活性:添加新状态或修改状态行为不涉及其他状态逻辑,利于扩展。
  • 消除条件分支:移除了大量基于状态判断的条件语句,提高了程序内聚性。

潜在挑战可能包括:

  • 过多具体状态类:随着状态数量增加,具体状态类的数量也会增长,可能影响系统组织结构简洁性。
  • 复杂状态转换逻辑:状态间转换规则复杂时,需额外关注状态转换的一致性和正确性。

总结

状态模式利用状态驱动的方式对对象行为进行有效管理,使得软件能够根据对象状态的变化动态调整行为。合理运用状态模式,可以提升系统对于复杂状态变化场景的适应能力,同时优化代码结构,保持高可维护性和扩展性。

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

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

相关文章

mybatis 集成neo4j实现

文章目录 前言一、引入jar包依赖二、配置 application.properties三、Mybatis Neo4j分页插件四、Mybatis Neo4j自定义转换器handler五、MybatisNeo4j代码示例总结 前言 MyBatis是一个基于Java语言的持久层框架,它通过XML描述符或注解将对象与存储过程或SQL语句进行…

Qt+VTK鼠标拾取点生成拉伸闭合三维体

程序示例精选 QtVTK鼠标拾取点生成拉伸闭合三维体 如需安装运行环境或远程调试,见文章底部个人QQ名片,由专业技术人员远程协助! 前言 这篇博客针对《QtVTK鼠标拾取点生成拉伸闭合三维体》编写代码,代码整洁,规则&…

java——特殊文件日志技术

目录 特殊文件Properties文件XML文件XML文件有如下的特点XML的作用和应用场景解析XML文件 日志技术概述日志技术的体系结构Logback日志框架概述快速入门核心配置文件logback.xml日志级别项目中使用日志框架 特殊文件 Properties文件 后缀为.properties的文件,称之…

k8s(2)

目录 一.二进制部署k8s 常见的K8S安装部署方式: k8s部署 二进制与高可用的区别 二.部署k8s 初始化操作: 每台node安装docker: 在 master01 节点上操作; 准备cfssl证书生成工具:: 执行脚本文件: 拉入etcd压缩包…

一文读懂!2024年NCDA数字绘画竞赛:参赛、要求、获奖作品

第12届未来设计师全国高校数字艺术设计大赛(NCDA) H类:数字绘画命题选项 命题信息 参赛对象: 1. 大学生组:分①研究生组②本科生组③专科生组,三组分别评审 2. 教师组:普通高校教师&#xf…

1.1_1 计算机网络的概念、功能、组成和分类

文章目录 1.1_1 计算机网络的概念、功能、组成和分类(一)计算机网络的概念(二)计算机网络的功能(三)计算机网络的组成1.组成部分2.工作方式3.功能组成 (四)计算机网络的分类 总结 1.…

windows11安装VMware----创建多虚拟机教程

一、centOS下载 1、官网地址:https://www.centos.org/ 2、阿里镜像站:https://mirrors.aliyun.com/centos 3、清华镜像源:https://mirrors.tuna.tsinghua.edu.cn/centos/ 3.、CentOS搜狐镜像:http://mirrors.sohu.com/centos/…

Linux-基础知识(黑马学习笔记)

硬件和软件 我们所熟知的计算机是由:硬件和软件组成。 硬件:计算机系统中电子,机械和光电元件等组成的各种物理装置的总称。 软件:是用户和计算机硬件之间的接口和桥梁,用户通过软件与计算机进行交流。 而操作系统…

个人博客系列-项目部署-nginx(3)

使用Nginx uwsgi进行部署django项目 一. 检查项目是否可以运行 启动项目 python manage.py runserver 0.0.0.0:8099输入ip:8099 查看启动页面 出现上述页面表示运行成功 二. 安装uwsgi并配置 2.1 下载uwsgi pip install uwsgi新建文件test.py写入内容,测试一…

SpringBoot中Redis缓存的使用

目录 1 前言 2 实现方法 2.1 查询数据时 2.2 修改数据 1 前言 对于一些不常改变,但又经常查询的数据,我们可以使用Redis缓存,来缓解数据库的压力,其中的逻辑如下: 2 实现方法 2.1 查询数据时 一般在控制类查询方…

Python列表:灵活多变的数据结构

文章目录 一、列表1.创建列表2.访问列表元素3.修改列表元素4.添加元素5.删除元素 二、列表脚本操作符1.连接运算符 2.重复运算符 * 三、列表函数&方法1.函数1.1 len() 函数1.2 max() 函数1.3 min() 函数1.4 sum() 函数1.5 list() 函数 2.方法2.1 append() 方法2.2 extend()…

MacBook的nginx出现13: Permission denied 的问题分析和解决办法

同样的项目代码,电脑从Windows更换到了MacBook,发现网站的样式都没有了,直接访问CSS文件 http://crm.ms-test.cc/toolstatic/css/bootstrap.min.css 发现无法访问。查看Nginx错误日志: 说明是nginx没有权限访问这个CSS文件&#…

mysql 分表实战

本文主要介绍基于range分区的相关 1、业务需求,每日160w数据,每月2000w;解决大表数据读写性能问题。 2、数据库mysql 8.0.34,默认innerDB;mysql自带的逻辑分表 3、分表的目的:解决大表性能差,小表缩小查询单位的特点(其实优化的精…

鼠标右键助手专业版 MouseBoost PRO for Mac v3.3.6中文破解

MouseBoost Pro mac版是一款简单实用的鼠标右键助手专业版,MouseBoost Pro for Mac只要轻点你的鼠标右键,就可以激活你想要的各种功能,让你的工作效率大幅度提高,非常好用。 软件下载:MouseBoost PRO for Mac v3.3.6中…

Gemma模型论文详解(附源码)

原文链接:Gemma模型论文详解(附源码) 1. 背景介绍 Gemma模型是在2023.2.21号Google新发布的大语言模型, Gemma复用了Gemini相同的技术(Gemini也是Google发布的多模态模型),Gemma这次发布了了2B和7B两个版本的参数,不…

如何快速卸载windows电脑的一些软件?

本系列是一些电脑常规操作的普及,有需要借鉴即可 注:每个电脑都会有差异,参考即可。 其实大部分软件你删除桌面上的图标不等于删除,因为桌面上的那个图标就是一个简单的快捷方式而已。 在这里插入图片描述 那如何正确的卸载软件呢…

Android 广播的基本概念

一.广播简介 Broadcast是安卓四大组件之一。安卓为了方便进行系统级别的消息通知,引入了一套广播消息机制。打个比方,记得原来在上课的时候,每个班级的教室里都会装有一个喇叭,这些喇叭都是接入到学校的广播室的,一旦…

(done) 什么是特征值和特征向量?如何求特征值的特征向量 ?如何判断一个矩阵能否相似对角化?

什么是齐次方程? https://blog.csdn.net/shimly123456/article/details/136198159 行列式和是否有解的关系? https://blog.csdn.net/shimly123456/article/details/136198215 特征值和特征向量 参考视频:https://www.bilibili.com/video/BV…

《Solidity 简易速速上手小册》第4章:智能合约的设计与开发(2024 最新版)

文章目录 4.1 合约结构和布局4.1.1 基础知识解析深入合约布局原则理解组织结构高效布局的重要性4.1.2 重点案例:构建一个在线商店合约案例 Demo:编写在线商店智能合约案例代码:OnlineStore.sol测试和验证拓展功能4.1.3 拓展案例 1:可升级的合约案例 Demo:创建可升级的智能…

【主题广范|见刊快】2024年科技,绿色能源和可持续发展国际会议(ICTGESD 2024)

【主题广范|见刊快】2024年科技,绿色能源和可持续发展国际会议(ICTGESD 2024) 2024 International Conference on Technology, Green Energy, and Sustainable Development ⊙会议简介: 2024年科技,绿色能源和可持续发…