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

状态模式

状态模式(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)来简化实现。

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

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

相关文章

Python爬虫知识体系-----Urllib库的使用

数据科学、数据分析、人工智能必备知识汇总-----Python爬虫-----持续更新:https://blog.csdn.net/grd_java/article/details/140574349 文章目录 1. 基本使用2. 请求对象的定制3. 编解码1. get请求方式:urllib.parse.quote()2. ur…

邦布带你从零开始实现图书管理系统(java版)

今天我们来从零开始实现图书管理系统。 图书管理系统 来看我们的具体的实现,上述视频。 我们首先来实现框架,我们要实现图书管理系统,首先要搭框架。 我们首先定义一个书包,在书包中定义一个书类和一个书架类,再定义…

数据库之常用函数

目录 一、数值函数 1.求绝对值函数 2.求余函数 3.用于获取整数的函数 4.获取随机数的函数 5.四舍五入函数 6.截取小数函数 二、字符串函数 1.返回字符串长度和字符串中字符个数的函数 2.合并字符串的函数 3.替换字符串的函数 4.字母大小写转换函数 5.获取指定长度…

Webpack、Vite区别知多少?

前端的项目打包,我们常用的构建工具有Webpack和Vite,那么Webpack和Vite是两种不同的前端构建工具,那么你们又是否了解它们的区别呢?我们在做项目时要如何选择呢? 一、工具定义 1、Webpack:是一个强大的静态模块打包工…

用Java手写jvm之实现查找class

写在前面 完成类加载器加载class的三阶段,加载,解析,初始化中的加载😀😀😀 源码 。 jvm想要运行class,是根据类全限定名称来从特定的位置基于类加载器来查找的,分别如下:…

go语言与UPX

源自:压缩工具之upx_51CTO博客_za压缩工具 下面是直接copy的: 在golang项目中, 最终运行的是打包好的二进制文件,如何才能让这个文件尽可能的小呢? 1.编译阶段的参数处理 go build使用的是静态编译,会将程序的依赖一起打包,这…

【SQL 新手教程 2/20】关系模型 -- 主键

💗 关系数据库建立在关系模型上⭐ 关系模型本质上就是若干个存储数据的二维表 记录 (Record): 表的每一行称为记录(Record),记录是一个逻辑意义上的数据 字段 (Column):表的每一列称为字段(Colu…

【算法】二进制常用操作

二进制常用操作 求n的二进制中第k位数字: n > > k & 1 n>>k\& 1 n>>k&1​ lowbit(x)的用法:返回x中最后一个1, l o w b i t ( x ) x & ( − x ) lowbit(x)x\&(-x) lowbit(x)x&(−x)​ 输入一个 32 位整数&a…

java如何同时继承接口和抽象类

java中要同时继承接口和抽象,需要用到的语句是 class 类名 extends 抽象类名 implements 接口 示例代码如下 interface Animal02{public String Name"牧羊犬";public void shout();public void info(); } abstract class Action01{public abstract voi…

解锁Vue的潜力:封装递归组件的经验之谈(网站导航层架嵌套)

最近在使用BootstrapVue写一个网站(我也不知道为啥要用这个😂),使用到了NavBarDropDown等一些组件的组合,可以自动创建一个响应式的效果,还不错。But…,这个DropDown只支持到二级。有人2019年就在Github上提了issue- dropdown submenu并且作者…

WebKit的CSS Aspect Ratio Box:重塑响应式设计

WebKit的CSS Aspect Ratio Box:重塑响应式设计 在响应式网页设计中,保持元素的宽高比是一个常见需求。幸运的是,CSS提供了一个名为aspect-ratio的属性,它允许开发者为元素定义一个理想的宽高比。在WebKit中,这个属性得…

吴恩达的TranslationAgent学习

TranslationAgent构成 整个[TranslationAgent (github.com)]在流程上分为短文本的一次性翻译和长文本的分chunk翻译(按照Token进行划分)。 但是不论长文本翻译还是短文本翻译,总体流程遵循执行、纠正再执行的逻辑循环实现。 这种按照自省思路…

数据库DDL | 增 删 改 操作 | 对数据库数据表

DDL建库建表(操作数据库/表)⭐️⭐️⭐️ 数据库 创建库 //create database 库名 create database xiaozhao2;查看库 //查看所有的库 show databases;删除库(危险操作) //drop database 库名 drop database xiaozhao2;使用库\切换库 //use 库名 use xiaozhao2;查看库数据…

【数字IC/FPGA】使用Verdi对比两个波形

步骤一: 使用verdi打开第一个波形 bsub verdi -ssf 1.fsdb添加需要观察的信号,如下图所示: 步骤二: 新建容器,依次点击Window --> Dock to --> New Container Window。 然后输入容器的名字,如下图所…

SQL数据库:通过在视频监控平台服务器上直接使用SQL存储过程,在海量记录中查询特定时间段内-某个摄像头的所有视频片段

目录 一、背景 1、存储过程 2、视频监控系统 二、需求和数据表 1、具体要求 2、数据表 3、部分数据 三、实现 1、目标 2、创建存储过程 (1)存储过程代码 (2)创建成功 3、存储过程的解释 4、SQL命令调用方式 5、调用…

Java----队列(Queue)

目录 1.队列(Queue) 1.1概念 1.2队列的使用 1.3队列的模拟实现 1.4循环队列 1.4.1循环队列下标偏移 1.4.2如何区分队列是空还是满 1.5双端队列 (Deque) 1.队列(Queue) 1.1概念 队列:只允许在一端进行插入数据…

训练的韧性:Mojo模型中自定义训练中断与恢复机制的实现

训练的韧性:Mojo模型中自定义训练中断与恢复机制的实现 在机器学习模型的开发过程中,训练过程可能会因为多种原因(如硬件故障、电源中断等)被迫中断。Mojo模型,作为一个泛指,可以代表任何机器学习或深度学…

Linux Redhat ens33不显示IP问题

优质博文:IT-BLOG-CN 【第一步】:查看系统网卡设备 : ip addr show 【第二步】:修改网卡配置参数 cd /etc/sysconfig/network-scripts/ vi ifcfg-ens33 修改ONBOOT参数为yes 【第三步】:重启网卡,然后ping检测…

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

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

MySQL - 优化概述

数据库性能取决于数据库层面的多个因素,例如表、查询和配置设置。这些软件构造会在硬件层面产生 CPU 和 I/O 操作,您必须尽量减少这些操作并使其尽可能高效。在致力于数据库性能优化时,您首先要了解软件方面的高级规则和指南,并使…