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

状态模式与订单状态机的实现

状态模式

状态模式(State Design Pattern)是一种行为设计模式,用于在对象的内部状态改变时改变其行为。这种模式可以将状态的变化封装在状态对象中,使得对象在状态变化时不会影响到其他代码,提升了代码的灵活性和可维护性。

状态设计模式的主要组成部分

  1. 上下文(Context):持有一个状态对象的引用,用于调用当前状态的行为。
  2. 状态接口(State Interface):定义一个接口,声明了状态对象的行为。
  3. 具体状态类(Concrete State Classes):实现状态接口,定义在特定状态下的具体行为。

实现步骤

1. 定义状态接口

定义一个状态接口或抽象类,声明所有具体状态类需要实现的方法。

public interface OrderState {void handlePayment(OrderContext context);void handleCancellation(OrderContext context);void handleCompletion(OrderContext context);
}
2. 实现具体状态类

每个具体状态类实现状态接口,定义在该状态下的具体行为。

public class PendingPaymentState implements OrderState {@Overridepublic void handlePayment(OrderContext context) {System.out.println("Processing payment...");context.setState(new PaidState());}@Overridepublic void handleCancellation(OrderContext context) {System.out.println("Order cancelled.");context.setState(new CancelledState());}@Overridepublic void handleCompletion(OrderContext context) {System.out.println("Order cannot be completed before payment.");}
}public class PaidState implements OrderState {@Overridepublic void handlePayment(OrderContext context) {System.out.println("Order already paid.");}@Overridepublic void handleCancellation(OrderContext context) {System.out.println("Order cancelled.");context.setState(new CancelledState());}@Overridepublic void handleCompletion(OrderContext context) {System.out.println("Order completed.");context.setState(new CompletedState());}
}public class CancelledState implements OrderState {@Overridepublic void handlePayment(OrderContext context) {System.out.println("Cannot process payment. Order is cancelled.");}@Overridepublic void handleCancellation(OrderContext context) {System.out.println("Order already cancelled.");}@Overridepublic void handleCompletion(OrderContext context) {System.out.println("Order cannot be completed after cancellation.");}
}public class CompletedState implements OrderState {@Overridepublic void handlePayment(OrderContext context) {System.out.println("Order already completed.");}@Overridepublic void handleCancellation(OrderContext context) {System.out.println("Order cannot be cancelled. It is already completed.");}@Overridepublic void handleCompletion(OrderContext context) {System.out.println("Order already completed.");}
}
3. 定义上下文类

上下文类持有一个当前状态的引用,并允许状态对象修改它的状态。

public class OrderContext {private OrderState currentState;public OrderContext() {// 默认初始状态currentState = new PendingPaymentState();}public void setState(OrderState state) {this.currentState = state;}public void handlePayment() {currentState.handlePayment(this);}public void handleCancellation() {currentState.handleCancellation(this);}public void handleCompletion() {currentState.handleCompletion(this);}
}

使用示例

你可以创建一个OrderContext实例,并通过调用状态处理方法来改变订单的状态。

public class Main {public static void main(String[] args) {OrderContext order = new OrderContext();order.handlePayment(); // 处理支付,状态变为PaidStateorder.handleCompletion(); // 完成订单,状态变为CompletedStateorder.handleCancellation(); // 无法取消,订单已完成}
}
总结

状态模式通过将状态行为分离到不同的状态类中,允许对象在其状态改变时改变其行为。这种模式提供了一种优雅的方式来处理状态变化,避免了在上下文类中使用大量的条件判断,提高了代码的可维护性和扩展性。在实际应用中,可以使用状态设计模式来管理各种状态驱动的行为,比如订单状态、工作流状态等。

订单状态机的实现

订单状态机的实现通常包括设计状态的枚举类型、定义状态转换规则和编写状态转换逻辑。下面是一个实现订单状态机的详细步骤和示例代码:

1. 定义订单状态枚举

首先定义一个枚举类型来表示订单的各种状态:

public enum OrderStatus {PENDING_PAYMENT, // 待支付PAID,            // 已支付CANCELLED,       // 已取消COMPLETED        // 已完成
}

2. 定义订单状态转换规则

通过状态机的方式定义各个状态之间的转换规则。可以使用第三方状态机库(如Spring State Machine)或者自定义状态机逻辑。下面是使用自定义状态机逻辑的示例:

public class OrderStateMachine {private OrderStatus currentState;public OrderStateMachine(OrderStatus initialState) {this.currentState = initialState;}public OrderStatus getCurrentState() {return currentState;}public boolean transition(OrderEvent event) {switch (currentState) {case PENDING_PAYMENT:if (event == OrderEvent.PAY) {currentState = OrderStatus.PAID;return true;} else if (event == OrderEvent.CANCEL) {currentState = OrderStatus.CANCELLED;return true;}break;case PAID:if (event == OrderEvent.COMPLETE) {currentState = OrderStatus.COMPLETED;return true;} else if (event == OrderEvent.CANCEL) {currentState = OrderStatus.CANCELLED;return true;}break;case COMPLETED:// Completed orders cannot transition to another statebreak;case CANCELLED:// Cancelled orders cannot transition to another statebreak;}return false; // Invalid transition}
}

3. 定义订单事件枚举

定义可以触发状态转换的事件:

public enum OrderEvent {PAY,       // 支付CANCEL,    // 取消COMPLETE   // 完成
}

4. 使用状态机处理订单状态转换

在订单服务中使用状态机来处理订单状态转换:

public class OrderService {public boolean processOrderEvent(Order order, OrderEvent event) {OrderStateMachine stateMachine = new OrderStateMachine(order.getStatus());boolean success = stateMachine.transition(event);if (success) {order.setStatus(stateMachine.getCurrentState());// 持久化订单状态到数据库orderRepository.save(order);}return success;}
}

5. 订单服务中的状态机集成示例

假设我们有一个订单服务类,在其中集成状态机逻辑:

@Service
public class OrderService {@Autowiredprivate OrderRepository orderRepository;public boolean createOrder(Order order) {order.setStatus(OrderStatus.PENDING_PAYMENT);orderRepository.save(order);return true;}public boolean payOrder(Long orderId) {Order order = orderRepository.findById(orderId).orElseThrow(() -> new OrderNotFoundException(orderId));return processOrderEvent(order, OrderEvent.PAY);}public boolean completeOrder(Long orderId) {Order order = orderRepository.findById(orderId).orElseThrow(() -> new OrderNotFoundException(orderId));return processOrderEvent(order, OrderEvent.COMPLETE);}public boolean cancelOrder(Long orderId) {Order order = orderRepository.findById(orderId).orElseThrow(() -> new OrderNotFoundException(orderId));return processOrderEvent(order, OrderEvent.CANCEL);}private boolean processOrderEvent(Order order, OrderEvent event) {OrderStateMachine stateMachine = new OrderStateMachine(order.getStatus());boolean success = stateMachine.transition(event);if (success) {order.setStatus(stateMachine.getCurrentState());orderRepository.save(order);}return success;}
}

总结

通过上述步骤,我们实现了一个简单的订单状态机,涵盖订单从创建到完成或取消的状态转换。使用状态机不仅使订单状态的管理更加清晰和可维护,还能够有效防止状态的不一致性,提高系统的可靠性。在实际项目中,可以根据具体需求选择使用状态机库(如Spring State Machine)来简化实现。

相关文章:

状态模式与订单状态机的实现

状态模式 状态模式(State Design Pattern)是一种行为设计模式,用于在对象的内部状态改变时改变其行为。这种模式可以将状态的变化封装在状态对象中,使得对象在状态变化时不会影响到其他代码,提升了代码的灵活性和可维…...

【MSP430】MSP430是什么?与STM32对比哪个性能更佳?

一、MSP430是什么? MSP430F5529LP是一款由德州仪器(TI)推出的16位微控制器单元(MCU)开发板,具有USB功能,内存配置为128KB闪存和8KB RAM,工作频率高达25MHz。 这款MCU以其高性能和多…...

Win11 操作(四)g502鼠标连接电脑不亮灯无反应

罗技鼠标连接电脑不亮灯无反应 前言 罗技技术💩中💩,贴吧技术神中神! 最近买了一个g502,结果买回来直接插上电脑连灯都不亮,问了一下客服。客服简单的让我换接口,又是下载ghub之类的&#xf…...

自定义QDialog使用详解

自定义QDialog使用详解 一、创建 QDialog 对象二、QDialog设置布局三、QDialog控制模态行为3.1 模态和非模态区别3.2 QDialog的模态使用四、使用 QDialogButtonBox五、处理对话框的结果六、使用 QDialog 的信号和槽QDialog是Qt框架中用于创建对话框窗口的基本类。对话框窗口通常…...

Pytorch使用教学2-Tensor的维度

在PyTorch使用的过程中,维度转换一定少不了。而PyTorch中有多种维度形变的方法,我们该在什么场景下使用什么方法呢? 本小节我们使用的张量如下: # 一维向量 t1 torch.tensor((1, 2)) # 二维向量 t2 torch.tensor([[1, 2, 3], …...

Interesting bug caused by getattr

题意:由 getattr 引起的有趣的 bug 问题背景: I try to train 8 CNN models with the same structures simultaneously. After training a model on a batch, I need to synchronize the weights of the feature extraction layers in other 7 models. …...

获取后端返回的图形验证码

如果后端返回的直接就是一个图形&#xff0c;有以下几种方式展示 一、直接在img标签里面的src里面调用接口 <img :src"dialogSrc" class"photo" alt"验证码图片" click"changeDialog">let orgUrl "/api/captcha" …...

奇怪的Excel单元格字体颜色格式

使用VBA代码修改单元格全部字符字体颜色是个很简单的任务&#xff0c;例如设置A1单元格字体颜色为红色。 Range("A1").Font.Color RGB(255, 0, 0)有时需要修改部分字符的颜色&#xff0c;如下图所示&#xff0c;将红色字符字体颜色修改为蓝色。代码将会稍许复杂&am…...

浅谈芯片验证中的仿真运行之 timescale (五)提防陷阱

一 仿真单位 timeunit 我们知道,当我们的代码中写清楚延时语句时,若不指定时间单位,则使用此单位; 例如: `timescale 1ns/1ps 则 #15 语句表示delay15ns; 例:如下代码,module a 的timescale是1ns/1ps, module b 是1ps/1ps; module b中的clk,频率是由输入参…...

uniapp 重置表单数据

场景 例如有数据如下 data(){return {queryForm:{value1:undefined,}} } 点击重置时候想重置form的数据&#xff0c; 操作 Object.assign(this.$data.queryForm, this.$options.data().queryForm); 就可以重置数据...

自学YOLO前置知识

YOLO前置知识 学习YOLO&#xff08;You Only Look Once&#xff09;之前&#xff0c;掌握一些前置知识会帮助你更好地理解和应用该技术。以下是一些推荐的前置知识领域&#xff1a; 计算机视觉基础&#xff1a; 图像处理&#xff1a;了解图像的基本处理技术&#xff0c;如滤波…...

Ubuntu18.04 编译报错: Could NOT find JNI

一、问题描述 Ubuntu18.04 编译报错 OpenCV 时&#xff0c;出现以下错误&#xff1a; Could NOT find JNI (missing: JAVA_INCLUDE_PATH JAVA_INCLUDE_PATH2 JAVA_AWT_INCLUDE_PATH)二、解决方法 先执行以下指令&#xff0c; export JAVA_HOME/usr/lib/jvm/java-8-openjdk-am…...

SQL labs-SQL注入(五,使用sqlmap进行cookie注入)

本文仅作为学习参考使用&#xff0c;本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 引言&#xff1a; Cookie 是一些数据, 存储于你电脑上的文本文件中。当 web 服务器向浏览器发送 web 页面时&#xff0c;在连接关闭后&#xff0c;服务端不会记录用户的信息。Cookie…...

C语言——内存管理

目录 前言 一、内存分类 1. 栈区&#xff08;Stack&#xff09; 2. 堆区&#xff08;Heap&#xff09; 3. 数据段&#xff08;Data Segment&#xff09; 4. 代码段&#xff08;Code Segment&#xff09; 二、内存分配方式 1、静态内存分配 2、栈内分配 3、动态内存分配 &#x…...

Unity UGUI 之 Image和Rawimage

本文仅作学习笔记与交流&#xff0c;不作任何商业用途 本文包括但不限于unity官方手册&#xff0c;唐老狮&#xff0c;麦扣教程知识&#xff0c;引用会标记&#xff0c;如有不足还请斧正 1.Image是什么 Unity - 手册&#xff1a;图像 精灵格式是什么&#xff1f; 1.2重要参数 …...

Lua 语法学习笔记

Lua 语法学习笔记 安装(windows) 官网&#xff1a;https://www.lua.org/ 下载SDK 解压&修改名称&#xff08;去除版本号&#xff09; 将lua后面的版本号去掉&#xff0c;如lua54.exe->lua.ext 配置环境变量 数据类型 数据类型描述nil这个最简单&#xff0c;只有值n…...

Prometheus配置alertmanager告警

1、拉取镜像并运行 1、配置docker镜像源 [rootlocalhost ~]# vim /etc/docker/daemon.json {"registry-mirrors": ["https://dfaad.mirror.aliyuncs.com"] } [rootlocalhost ~]# systemctl daemon-reload [rootlocalhost ~]# systemctl restart docker2、…...

.net core 外观者设计模式 实现,多种支付选择

1&#xff0c;接口 /// <summary>/// Web页面支付/// </summary>public interface IWebPagePay{public WebPagePayResult CreatePay(string productName, string orderSn, string totalPrice);}2&#xff0c;实现接口 实现阿里支付 public class AliPagePay : IWe…...

Matlab 命令行窗口默认输出(异常)

目录 前言Matlab 先验知识1 异常输出的代码2 正常输出的代码 前言 在单独调试 Matlab 写的函数时出现不想出现的异常打印值&#xff0c;逐个注释排查才找到是 if elseif else 代码块的问题&#xff0c;会默认打印输出 else 部分第一个返回值的值&#xff08;下方代码中的 P值&…...

LeetCode/NowCoder-二叉树OJ练习

励志冰檗&#xff1a;形容在清苦的生活环境中激励自己的意志。&#x1f493;&#x1f493;&#x1f493; 目录 说在前面 题目一&#xff1a;单值二叉树 题目二&#xff1a;相同的树 题目三&#xff1a;对称二叉树 题目四&#xff1a;二叉树的前序遍历 题目五&#xff1a;另…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

解析两阶段提交与三阶段提交的核心差异及MySQL实现方案

引言 在分布式系统的事务处理中&#xff0c;如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议&#xff08;2PC&#xff09;通过准备阶段与提交阶段的协调机制&#xff0c;以同步决策模式确保事务原子性。其改进版本三阶段提交协议&#xff08;3PC&#xf…...

负载均衡器》》LVS、Nginx、HAproxy 区别

虚拟主机 先4&#xff0c;后7...

goreplay

1.github地址 https://github.com/buger/goreplay 2.简单介绍 GoReplay 是一个开源的网络监控工具&#xff0c;可以记录用户的实时流量并将其用于镜像、负载测试、监控和详细分析。 3.出现背景 随着应用程序的增长&#xff0c;测试它所需的工作量也会呈指数级增长。GoRepl…...