首页 > 其他分享 >状态设计模式

状态设计模式

时间:2024-04-28 17:45:33浏览次数:19  
标签:状态 快照 状态机 订单 支付 设计模式 变更

为什么使用这个状态设计模式?
在预约下单模块设计订单状态的时候有7种,用户下单之后变更为待支付,如果取消订单就修改为已取消,如果支付了就修改为派单中,之后服务人员和机构进行抢单或派单修改为待服务、开始服务修改为服务中、订单完成之后修改为已完成。如果有一处用户想取消订单,需要自动退款并将订单状态修改为已关闭。
在上述过程中原本是对订单状态进行硬编码的,如果有一天更改了业务逻辑就需要更改代码,不方便系统扩展和维护,另外订单状态的管理散落在很多地方不方便对订单状态进行统一管理和维护,所以我们使用了状态机来对订单状态进行统一管理

状态设计模式有四个要素:现态、事件、动作、次态
现态:指当前所处的状态
事件:当一个条件被满足,状态会由现态变为新的状态,事件发生会触发一个动作,或者执行一次状态的迁移
动作:发生事件执行的动作,动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态,动作不是必须的,当条件满足后,也可以不执行任何动作,直接迁移到新状态
次态:条件满足后要迁往的新状态

拿支付订单到派单中状态举例:用户下单之后,订单处于待支付状态,用户支付后修改订单状态为派单中
现态:订单当前处于待支付状态那么现态为待支付
事件:用户支付成功为事件,支付成功是条件,当条件满足进行状态迁移
动作:将订单状态由待支付更改为派单中
次态:派单中

实现订单状态机需要的步骤
1.添加需要的组件依赖
组件中包含了以下内容:
核心抽象类:定义了状态机的操作逻辑,如状态初始化、变更及其持久化处理
状态快照:用于记录业务数据的当前状态,方便恢复和追踪
状态事件和处理:定义状态变更事件及其处理逻辑,确保状态转换的正确性
持久化服务:负责状态信息的存储和读取,保存状态机的持久性和一致性
业务快照服务:处理业务数据快照的存储和查询,支持业务的回溯和状态恢复

2.添加订单状态枚举类
订单状态枚举类定义了订单在其生命周期中可能遇到的不同状态

3.添加事件枚举类
事件枚举类定义了订单在处理过程中可能经历的状态变更事件。每个事件由四个部分构成:源状态、目标状态、事件描述和事件名称

4.定义订单快照类
订单快照类是一个数据传输对象(DTO),它扩展了状态机快照的基类,用于表示订单的当前状态快照。订单快照是状态机中一个关键组件,用于记录和追踪订单在其生命周期中的状态变化。这个DTO包括了订单的详细信息,如订单状态、金额、时间戳等,确保可以对订单状态的每次变更进行详细追踪。
此外,OrderSnapshotDTO重写了状态机快照接口中的方法,包括获取和设置快照ID与状态,这使得状态机能够更容易地管理和引用订单状态。通过这种方式,我们可以确保每次状态变更都能被准确记录和恢复,这对于订单处理流程的稳定性和可靠性是非常关键的

5.定义动作类
是订单支付成功的事件处理器,实现了状态变更处理器接口。它主要负责处理订单从“待支付”状态成功转变为“支付成功”状态后的逻辑。当订单支付事件被触发时,该处理器会被调用。
具体来说,处理器中的 handler 方法接收业务ID(即订单ID),状态变更事件以及与订单相关的快照数据。在这个方法中,我们记录处理逻辑开始的日志,并执行与订单状态更新相关的业务操作,如更新订单状态、通知用户支付成功等。

6.定义订单状态机类
订单状态机类是一个特定于订单的状态机,继承自一个抽象的状态机基类,专门用于管理订单状态的变化。订单状态机是系统中关键的一部分,用于确保订单在其生命周期中状态转换的正确性和一致性。

主要功能包括:
构造器:接收状态机持久化程序、业务快照服务和Redis处理程序作为依赖,这些都是管理状态机所需的核心组件。
设置状态机名称:返回状态机的名称为"order",这个名称在系统中用于标识和管理与订单相关的状态变更。
设置初始状态:定义状态机的初始状态为NO_PAY(待支付),这是订单创建后的起始状态。
后处理方法:postProcessor 方法可以在状态变更后可以执行额外的逻辑,比如记录日志、发送通知等。

7.状态机使用MySQL对状态进行持久化
状态机持久化表 (state_persister):
此表用于记录每个业务实体(如订单或服务单)在状态机中的当前状态。
包含字段如state_machine_name(状态机名称,如order或serve),biz_id(业务ID,即订单ID),以及state(当前状态)。
表设计还包括时间戳字段create_time和update_time以追踪记录的创建和更新时间。
使用唯一索引约束state_machine_name和biz_id的组合,确保每个业务ID在其状态机中的唯一性。
状态机快照表 (biz_snapshot):
用于存储业务实体(如订单)在状态变更每个阶段的详细数据快照,以便于查询订单的历史变化。
字段包括state_machine_name,biz_id(与持久化表相同),以及state(快照对应的状态)。
biz_data字段以JSON格式存储订单的详细信息,如金额、状态、时间等。
同样包含create_time和update_time字段,记录快照的创建和更新时间。
db_shard_id字段用于将来可能的数据库分片需求。
通过这两个表,系统能够有效地管理和追踪订单在其生命周期内的状态变更和详细历史

使用订单状态机
例如:
1.加载订单状态机
使用@Import注解将订单状态机导入
2.启动状态机
2.1下单时启动状态机
下单后创建一个新订单,使用状态机的启动方法表示用状态机对该订单的状态开始进行管理
并且将状态机的操作放在业务方法中,并与业务逻辑一起在同一个事务中执行,任何状态机的失败都会导致整个事务的回滚,从而防止了状态不一致的发生

2.2支付成功时使用状态机
定义状态变更处理器:
在订单支付成功处理器(OrderPayedHandler)中,我们专注于处理订单从“待支付”状态到“派单中”状态的转变。处理器首先确认支付信息,包括支付状态、时间、服务商交易单号和第三方支付交易单号等。
这些信息被组织在一个OrderSnapshotDTO对象中,该对象代表了订单的当前状态快照。
使用Spring的@Component注解定义处理器,并通过"order_payed"命名,遵循状态机名称_事件名称的命名规则,以确保系统能正确识别和调用处理器。
支付成功状态变更逻辑:
在处理器的handler方法中,根据业务ID(订单ID)和状态变更事件来更新订单状态。
使用ordersService.updateStatus方法来持久化状态变更。如果更新失败,则抛出DbRuntimeException异常,确保事务能回滚并保持数据一致性。
在业务流程中触发状态变更:
在支付成功的业务方法paySuccess中,首先验证订单当前的支付状态是否为“待支付”,确保不对已处理的订单重复操作。
验证支付通知中的第三方支付单号,确保支付信息的完整性。
构建支付相关的订单快照信息,并调用状态机的changeStatus方法来正式触发状态变更。
此方法同样包裹在@Transactional注解中,确保整个支付成功处理过程的事务性,包括订单状态的更新和支付信息的记录。

标签:状态,快照,状态机,订单,支付,设计模式,变更
From: https://www.cnblogs.com/zhao-zong-yu-hai/p/18164194

相关文章

  • Linux资源监控命令(系统资源占用top,磁盘使用情况df,网络状态监控sar)
    top:系统资源占用    df:磁盘使用情况   sar:网络状态top命令查看cpu,内存使用情况,类似Windows的任务处理器  退出命令:ctrl+ctop命令内容详解1.PLD:进程id2.USER:进程所属用户3.PR:进程优先级,越小越高4.NI:负值表示高优先级,正表示低优先级5.VIRT:......
  • 系统整容纪:责任链设计模式的应用实战(爆灯了,研发工期由45天降为1天)
    本文通过介绍使用责任链设计模式的背景和经历,来使得读者加深对于此设计模式的印象,甚至受到一定的启发来对自己当下所参与、所负责的项目进行“整容”,从而提升系统的“美感”。分享工作中的点点滴滴。一、背景在下所负责的系统中有这么一个模块,分区模块,直接看这个词的话相信很......
  • js设计模式(上)
     引用:(23条消息)《Javascript设计模式与开发实践》关于设计模式典型代码的整理(上):单例模式、策略模式、代理模式、迭代器模式、发布-订阅模式、命令模式、组合模式_QQsilhonette的博客-CSDN博客1、单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。使用闭包封装......
  • vue3 快速入门系列 —— 状态管理 pinia
    其他章节请看:vue3快速入门系列Piniavue3状态管理这里选择pinia。虽然vuex4已支持Vue3的CompositionAPI,但是vue3官网推荐新的应用使用pinia——vue3pinia集中式状态管理redux、mobx、vuex、pinia都是集中式状态管理工具。与之对应的就是分布式。Pinia符......
  • AI模块(有限状态机、行为树)-应用在cocos中
    前言:本模块是在cocos项目中运用战斗框架,根据学习别人的文章来结合项目进行编写的,若有不对不合理的地方有劳大家指正,万分感谢!!!若有能有用的上的,万分荣幸!简介:AI模块一般是对怪物的AI实现,或者托管等自动战斗的情况。具体方式可能根据项目的具体需求来选择,常用的有:有限状态机,行为树......
  • 设计模式
    设计模式的七大原则1、开闭原则(OpenClosePrinciple)开闭原则的意思是:对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中......
  • 设计模式
    设计模式六大原则1、开放封闭原则OpenClosePrincipleOCP:尽量通过扩展软件实体来解决需求变化,而不是通过修改已有的代码来完成变化OCP原则要求设计者在需要修改现有代码时,不应该直接修改已有的代码,而是应该通过扩展现有代码来实现新的功能或修改。代码实例:实现计算机:Ope......
  • 常用设计模式-单例模式
    单例模式(保证只有一个实例,并只提供一个访问实例的访问点)单例模式的创建方式:饿汉模式-静态变量packagecom.pattern;//饿汉模式-静态变量publicclassSingleton{//类初始化时,会立即加载该对象,线程天生安全,调用效率高privatestaticfinalSingletons......
  • 记录一次责任链设计模式使用低级错误
    记录一次责任链设计模式使用低级错误目录记录一次责任链设计模式使用低级错误背景流程发现问题解决方案总结背景提供一个服务支持语音转写成文本,以及历史转写备份数据的简单服务。提供一个接口批量上传,一次最大1000条(分表)落库之后同时发送到消息队列并更新数据状态消费......
  • 开启、关闭HDD读、写缓存状态
    sg3一、sg3查看缓存状态您可以使用sg_modes命令来查看SAS盘和SATA盘的缓存状态。例如,要查看/dev/sdb设备的缓存状态,您可以执行以下命令:sg_modes-p8,0/dev/sdb二、sg3关闭机械盘写缓存状态(仅适用于SAS盘)对于SAS盘,您可以按照以下步骤更改其读写缓存状态:1、编辑缓存状态......