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

文章目录

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

一、技术背景与应用场景

状态模式是一种行为设计模式,用于处理一个对象在其内部状态改变时,其行为也随之发生相应变化的情况。例如,在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,一经查实,立即删除!

相关文章

loop_list单向循环列表

#include "loop_list.h" //创建单向循环链表 loop_p create_head() { loop_p L(loop_p)malloc(sizeof(loop_list)); if(LNULL) { printf("create fail\n"); return NULL; } L->len 0; L->nextL; retur…

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压缩包…

Unity架构师经验分享:基于状态机的逻辑控制

在Unity中,状态机是一种非常重要的设计模式,它可以帮助开发者更好地管理游戏中的逻辑控制。在本文中,我们将详细解答基于状态机的逻辑控制,帮助Unity架构师进阶。 1. 什么是状态机? 状态机是一种用于描述对象在不同状…

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

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

mybatis总结三

传统do实现方式&#xff1a; public class StudentDaoImpl implements StudentDao {Overridepublic List<Student> selectStudents() {SqlSession sqlSession MybatisUtils.getSqlSession();String sqlId "com.lifang.dao.StudentDao.selectStudents";List&…

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

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

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

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

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

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

个人博客系列-项目部署-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写入内容&#xff0c;测试一…

SpringBoot中Redis缓存的使用

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

绕过5秒盾Cloudflare和DDoS-GUARD

绕过5秒盾Cloudflare和DDoS-GUARD 5秒盾的特点免费版5秒盾的绕过方法付费版5秒盾的绕过方法 5秒盾的特点 <title>Just a moment...</title>例如: <!DOCTYPE html><html lang"en-US"><head><title>Just a moment...</title&…

Linux文件上传下载与MySQL安装常见问题

Linux文件上传和下载 在FinalShell中拖拽上传文件 双击下载文件 或者 yun -y install lrzsz 安装此命令 rz 进行文件上传 sz 进行文件下载 Linux系统常用的压缩格式 tar格式 归档文件&#xff0c;整合到一个文件内&#xff0c;无压缩效果 gzip格式 gzip压缩文件&…

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 的问题分析和解决办法

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

Mockito测试框架入门与使用

目录 MockitoMockito使用Mockito依赖Mockito常用注解Mockito常用方法 Mockito Mockito 是一个流行的 Java 单元测试框架&#xff0c;用于模拟&#xff08;mock&#xff09;对象以便进行单元测试。它可以帮助开发人员创建和管理模拟对象&#xff0c;以便在测试过程中替换那些不…

mysql 分表实战

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

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

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