当前位置: 首页 > news >正文

设计模式学习(十二)状态模式

目录

    • 一、定义
      • 1.1 什么是状态模式?
      • 1.2 状态模式的优缺点
      • 1.3 状态模式的实现结构
    • 二、适用场景
    • 三、代码示例:订单状态管理
      • 3.1 背景介绍
      • 3.2 问题分析
      • 3.3 状态模式解决方案
        • 1)定义状态接口
        • 2)实现具体状态类
        • 3)定义环境类
        • 4)客户端测试
        • 4)测试结果

一、定义

1.1 什么是状态模式?

状态模式(State Pattern) 是一种 行为型 设计模式,对有状态的对象,把复杂的 “判断逻辑” 提取到不同的状态对象中,允许状态对象在其内部状态发生改变时,改变其行为。

1.2 状态模式的优缺点

状态模式的优点:

  1. 结构清晰 :状态模式将与特定状态相关的行为局部化道一个状态中,并且将不同状态的行为分割开来,满足 “但一职责原则”。
  2. 将状态转换显示化:减少对象间的相互依赖,将不同的状态引入独立的对象中会是的状态转换变得更加明确,且减少对相见的相互依赖。
  3. 状态类职责明确:有利于程序的扩展。通过定义新的子类很容易地增加新的状态和转换。

状态模式的缺点:

  1. 状态模式的使用必然会增加系统的类与对象的个数。
  2. 状态模式的结构与实现都较为复杂,如果使用不当会导致程序结构和代码的混乱。
  3. 状态模式对开闭原则的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源码,否则无法切换到新增状态,而且修改某个状态类的行为也需要修改对应类的源码。

1.3 状态模式的实现结构

状态模式把受环境改变的对象行为包装在不同的状态对象里,其意图是让一个对象在其内部状态改变的时候,其行为也随之改变。现在我们来分析其基本结构和实现方法。

状态模式主要包含三个角色:

  • Context(环境类):定义客户端感兴趣的接口,维护一个 State 子类的实例,这个示例定义当前状态。
  • State(抽象状态类):定义一个接口,用以封装 Context 的特定状态相关的行为。
  • ConcreteState(具体状态类):每一个子类实现一个与 Context 的一个状态相关的行为。

二、适用场景

适用场景一:算法框架固定的场景

  • 适用原因:当多个相关类需要执行相同的工作流程或算法骨架,但其中某些具体步骤的实现各不相同。这些类共享一个通用的操作序列,只是在特定环节存在差异化实现。
  • 状态模式解决的问题:消除重复的过程控制代码,确保所有子类都遵循相同的执行顺序和流程规范。避免了在每个具体类中重复编写相同的流程控制逻辑,同时也防止了因流程修改需要在多个地方同步更新的维护负担。

适用场景二:代码复用的场景

  • 适用原因:系统中存在多个类包含大量相同的行为代码,只有部分核心逻辑存在差异。这些类在整体功能上高度相似,但在关键步骤上需要个性化实现。
  • 状态模式解决的问题:通过将公共代码提升到父类中,显著减少代码重复。当公公逻辑需要修改时,只需在父类中修改一处即可影响所有子类,大大提高了代码的可维护性和一致性。

适用场景三:控制子类扩展的场景

  • 适用原因:需要确保子类在扩展时不会破坏核心算法的结构,或者需要限制子类只能重写特定的操作步骤。系统要求对扩展行为进行规范化管理。
  • 解决的问题:防止子类随意修改关键流程,确保系统的稳定性和一致性。通过模板方法定义不可更改的算法骨架,既保证了扩展的灵活性,又维护了核心流程的稳定性。

三、代码示例:订单状态管理

3.1 背景介绍

在电商系统下,订单状态管理是一个典型的状态模式应用场景。订单会经历从创建到完成的多个状态,每个状态下可执行的操作各不相同。

3.2 问题分析

如果不使用状态模式,我们可能会写出这样的代码:

public class Order {private String state;public void handle() {if ("pending".equals(state)) {System.out.println("订单待支付,可以支付或取消");} else if ("paid".equals(state)) {System.out.println("订单已支付,可以发货");} else if ("shipped".equals(state)) {System.out.println("订单已发货,等待确认收货");} else if ("completed".equals(state)) {System.out.println("订单已取消,不能进行任何操作");}}public void pay() {if ("pending".equals(state)) {state = "paid";System.out.println("支付成功");} else {System.out.println("当前状态不能支付");}}
}

这种方式的缺点很明显:

  • 大量的 if-else 语句,代码臃肿;
  • 违反开闭原则,新增状态需要修改原有代码;
  • 状态转换逻辑分散在各个方法中,难以维护;

3.3 状态模式解决方案

代码 UML 如下:

CancelledState
+handle(OrderContext)
+cancel(OrderContext)
+pay(OrderContext)
+ship(OrderContext)
+confirm(OrderContext)
CompletedState
+confirm(OrderContext)
+cancel(OrderContext)
+pay(OrderContext)
+handle(OrderContext)
+ship(OrderContext)
OrderContext
+confirm()
+handle()
+getState()
+pay()
+setState(OrderState)
+getOrderId()
+cancel()
+ship()
«Interface»
OrderState
+pay(OrderContext)
+ship(OrderContext)
+confirm(OrderContext)
+handle(OrderContext)
+cancel(OrderContext)
PaidState
+handle(OrderContext)
+ship(OrderContext)
+cancel(OrderContext)
+confirm(OrderContext)
+pay(OrderContext)
PendingState
+ship(OrderContext)
+handle(OrderContext)
+confirm(OrderContext)
+cancel(OrderContext)
+pay(OrderContext)
ShippedState
+pay(OrderContext)
+ship(OrderContext)
+confirm(OrderContext)
+cancel(OrderContext)
+handle(OrderContext)
StatePatternDemo
+main(String[])
1)定义状态接口
/*** 订单状态接口*/
public interface OrderState {void handle(OrderContext context);void pay(OrderContext context);void ship(OrderContext context);void confirm(OrderContext context);void cancel(OrderContext context);
}
2)实现具体状态类
/*** 待支付状态*/
public class PendingState implements OrderState {@Overridepublic void handle(OrderContext context) {System.out.println("订单待支付,可以支付或取消");}@Overridepublic void pay(OrderContext context) {System.out.println("支付成功,订单状态变为已支付");context.setState(new PaidState());}@Overridepublic void ship(OrderContext context) {System.out.println("待支付状态不能发货");}@Overridepublic void confirm(OrderContext context) {System.out.println("待支付状态不能确认收货");}@Overridepublic void cancel(OrderContext context) {System.out.println("订单已取消");context.setState(new CancelledState());}
}/*** 已支付状态*/
public class PaidState implements OrderState {@Overridepublic void handle(OrderContext context) {System.out.println("订单已支付,可以发货或取消");}@Overridepublic void pay(OrderContext context) {System.out.println("订单已支付,无需重复支付");}@Overridepublic void ship(OrderContext context) {System.out.println("发货成功,订单状态变为已发货");context.setState(new ShippedState());}@Overridepublic void confirm(OrderContext context) {System.out.println("已支付状态不能确认收货");}@Overridepublic void cancel(OrderContext context) {System.out.println("取消订单,退款处理中");context.setState(new CancelledState());}
}/*** 已发货状态*/
public class ShippedState implements OrderState {@Overridepublic void handle(OrderContext context) {System.out.println("订单已发货,等待确认收货");}@Overridepublic void pay(OrderContext context) {System.out.println("已发货状态不能支付");}@Overridepublic void ship(OrderContext context) {System.out.println("订单已发货,不能重复发货");}@Overridepublic void confirm(OrderContext context) {System.out.println("确认收货,订单完成");context.setState(new CompletedState());}@Overridepublic void cancel(OrderContext context) {System.out.println("已发货状态不能取消,请联系客服");}
}/*** 已完成状态*/
public class CompletedState implements OrderState {@Overridepublic void handle(OrderContext context) {System.out.println("订单已完成,可以评价");}@Overridepublic void pay(OrderContext context) {System.out.println("订单已完成,不能支付");}@Overridepublic void ship(OrderContext context) {System.out.println("订单已完成,不能发货");}@Overridepublic void confirm(OrderContext context) {System.out.println("订单已完成,不能重复确认");}@Overridepublic void cancel(OrderContext context) {System.out.println("订单已完成,不能取消");}
}/*** 已取消状态*/
public class CancelledState implements OrderState {@Overridepublic void handle(OrderContext context) {System.out.println("订单已取消,不能进行任何操作");}@Overridepublic void pay(OrderContext context) {System.out.println("订单已取消,不能支付");}@Overridepublic void ship(OrderContext context) {System.out.println("订单已取消,不能发货");}@Overridepublic void confirm(OrderContext context) {System.out.println("订单已取消,不能确认收货");}@Overridepublic void cancel(OrderContext context) {System.out.println("订单已取消,不能重复取消");}
}
3)定义环境类
/*** 订单上下文类*/
public class OrderContext {private OrderState state;private String orderId;public OrderContext(String orderId) {this.orderId = orderId;// 初始状态为待支付this.state = new PendingState();}public void setState(OrderState state) {this.state = state;}public OrderState getState() {return state;}// 委托给状态对象处理public void handle() {state.handle(this);}public void pay() {state.pay(this);}public void ship() {state.ship(this);}public void confirm() {state.confirm(this);}public void cancel() {state.cancel(this);}public String getOrderId() {return orderId;}
}
4)客户端测试
/*** 测试类*/
public class StatePatternDemo {public static void main(String[] args) {OrderContext order = new OrderContext("ORDER001");// 初始状态order.handle();order.pay();// 已支付状态order.handle();order.ship();// 已发货状态order.handle();order.confirm();// 已完成状态order.handle();order.cancel();System.out.println("====================================");// 测试异常流程OrderContext order2 = new OrderContext("ORDER002");order2.ship(); // 待支付状态尝试发货order2.cancel(); // 取消订单order2.pay(); // 已取消状态尝试支付}
}
4)测试结果

执行 main() 之后,结果如下所示:

整理完毕,完结撒花~🌻





参考地址:

1.状态模式(State模式),https://blog.csdn.net/qq_35784669/article/details/121238278

http://www.dtcms.com/a/569114.html

相关文章:

  • shell-基于k8s/docker管理容器、监控模型训练所消耗的最大CPU与最大内存脚本
  • Maven打包时指定输出路径、以时间戳命名包名和路径名,结合IDEA以指令脚本方式动态配置输出目录
  • PortSwigger
  • Doxygen入门指南:从注释到自动文档
  • Docker 部署 Elasticsearch 8.12 + Kibana + Nginx 负载均衡
  • yolo 训练 动态改变类别
  • SQL大表关联优化全攻略
  • 第五章:构建用户界面(UMG) - 游戏内HUD
  • CSS 雪碧图和 SVG 雪碧图的原理和区别
  • 网站底部代码特效邢台网红隧道
  • 网站降权表现营销型公司网站有哪些
  • 评估指标+数据不匹配+贝叶斯最优误差(分析方差和偏差)+迁移学习+多任务学习+端到端深度学习
  • 外国食品优秀设计网站做网站电话销售
  • 构建下一代法律智能助手:需求分析、资源整合与系统设计
  • Oracle AWR案例分析:精准定位SQL执行计划切换的时间点
  • 2025年7月一区SCI优化算法-Logistic-Gauss Circle optimizer-附Matlab免费代码
  • abpVnext 获取token报错,配置文件从sqlerver切换到oracle,再切换回来sqlerver无法获取token
  • 成都哪里有做网站的公司wordpress在本地搭建
  • C++进阶:(四)set系列容器的全面指南
  • 【Java零碎知识点】----- java.util.Random 与 Math.random()
  • 补充内容:YOLOv5损失函数解析+代码阅读
  • 北仑网站建设培训学校游戏开发需要什么学历
  • 高端装备制造提速,紧固件标准化与智能化升级成为行业新焦点
  • 6项提高电机制造质量的电气测试方案
  • 09_FastMCP 2.x 中文文档之FastMCP高级功能服务器组成详解
  • 工业之“眼”的进化:基于MEMS扫描的主动式3D视觉如何驱动柔性制造
  • 基于管理会计的制造企业运营优化虚拟仿真实验
  • 工业制造领域的ODM、OEM、EMS、JDM、CM、OBM都是啥
  • 建设网站要用什么软件.net程序员网站开发工程师
  • day07(11.4)——leetcode面试经典150