说明:本文只是在个人实战中的示例,主要了解思想,代码可根据自己的具体情况进行调整,不是完整的demo代码。
背景说明订单存在下单、支付、运输、完成等此类的状态流转,每一个状态下做不同的业务处理,状态存在变更的情况。
期望能够通过配置来实现状态变更时不影响历史代码并且不做变更,仅针对新状态进行业务开发即可。
个人的解决方案是这样的,仅供参考:
1、状态具体的流转步骤通过配置文件完成
2、每个状态要做的业务逻辑面向接口开发
3、使用指令模式来进行控制
4、具体指令配置在配置文件中
5、指令就是状态code
6、通过策略模式进行封装仅对外暴露一个接口
7、通过桥连接模式将具体的状态机流转进行处理
- 梳理自己所需要的状态,每一个状态code就是一个指令
- 每一个指令对应了一个具体的业务接口实现类
- 不同的产品可能有不同的状态流转,需要支持多产品集合
配置文件示例如下,代码仅供参考,可根据自己的业务进行不同的字段增减:
配置内容我写在了bootstrap.yml文件中了,根据自己的业务进行调整
#自定义状态机 statemachine: products: #产品集合 - name: gome_cuohe #产品标识 open: true #产品启用开关 states: #产品状态集合 #角色分别为:系统(SYSTEM)、雇主(A)、服务商(B) - service: OrderStateMachineXXXServiceImpl #状态机需要执行的service roles: A,B#支持的角色 instructions: xxx #指令 des: #描述 - service: OrderStateMachineSelectYYYServiceImpl #状态机需要执行的service roles: B#支持的角色 instructions: yyy #指令 des: #描述
创建对应配置内容的映射java类
@Data @Configuration @ConfigurationProperties(prefix = "statemachine") public class StateMachineConfig { Listproducts = Lists.newArrayList(); }
@Data public class StateMachineProduct { String name; Boolean open; Liststates = Lists.newArrayList(); }
@Data public class StateMachineProductState { String service; String roles; String instructions; String des; }第二步、定义状态机接口
状态机具体执行的service接口定义
public interface OrderStateMachineService { OrderInstructionsStateVO execute(OrderInstructionsModel model); boolean checkState(OrderInstructionsModel model); }
入参Model
@Data public class OrderInstructionsModel { String productsName;//产品名称 String instructions;//指令 String role;//角色 Long userId;//用户ID Object dto;//入参对象 }
出参VO
@Data public class OrderInstructionsStateVO { String code; String msg; Object data; }第三步、状态机业务实现
yml配置文件中每一个service都实现了OrderStateMachineService 接口
注意:Service的注解值对应yml文件中service的配置
下面的代码仅供参考:
@Slf4j @Service("OrderStateMachineXXXServiceImpl") public class OrderStateMachineXXXServiceImpl implements OrderStateMachineService { @Transactional(rollbackFor = Exception.class) @Override public OrderInstructionsStateVO execute(OrderInstructionsModel model){ //TODO Your code return null; } @Override public boolean checkState(OrderInstructionsModel model){ //TODO Your check return true; } }
@Slf4j @Service("OrderStateMachineYYYServiceImpl") public class OrderStateMachineYYYServiceImpl implements OrderStateMachineService { @Transactional(rollbackFor = Exception.class) @Override public OrderInstructionsStateVO execute(OrderInstructionsModel model){ //TODO Your code return null; } @Override public boolean checkState(OrderInstructionsModel model){ //TODO Your check return true; } }第四步、定义对外暴露的接口
public interface OrderInstructionsService { OrderInstructionsStateVO orderInstructions(OrderInstructionsModel model); }第五步、实现对外暴露的接口
@Service public class OrderInstructionsServiceImpl implements OrderInstructionsService { @Autowired private StateMachineConfig stateMachineConfig;//状态机配置,用于校验匹配 @Override public OrderInstructionsStateVO orderInstructions(OrderInstructionsModel model) { String instructions = model.getInstructions(); String productsName = model.getProductsName(); String role = model.getRole(); if(StringUtils.isEmpty(instructions) || StringUtils.isEmpty(productsName) || StringUtils.isEmpty(role)){ OrderInstructionsStateVO orderInstructionsStateVO = new OrderInstructionsStateVO(); orderInstructionsStateVO.setCode("404"); orderInstructionsStateVO.setMsg("参数不全"); return orderInstructionsStateVO; } Listproducts = stateMachineConfig.getProducts(); for (StateMachineProduct stateMachineProduct: products) { String name = stateMachineProduct.getName(); if(name.equals(productsName) && stateMachineProduct.getOpen()){ List states = stateMachineProduct.getStates(); for (StateMachineProductState stateMachineProductState : states) { String instructionsState = stateMachineProductState.getInstructions(); String rolesState = stateMachineProductState.getRoles(); if(instructionsState.equals(instructions)){ if(rolesState.indexOf(role) != -1){ String service = stateMachineProductState.getService(); OrderStateMachineService stateService = (OrderStateMachineService) SpringContextUtil.getBean(service); OrderInstructionsStateVO vo = stateService.execute(model); return vo; } } } } } OrderInstructionsStateVO orderInstructionsStateVO = new OrderInstructionsStateVO(); orderInstructionsStateVO.setCode("400"); orderInstructionsStateVO.setMsg("未匹配到状态机"); return orderInstructionsStateVO; } }
目前我写到这个程度,还有很多可以优化的地方,优化的方向应该是:
只需要修改配置不影响具体的业务逻辑。
比如,增加指令:nextInstructions #下一状态
大致的结构框架就是这样的。
也可以进行二次抽象,通过组合模式来实现不同的产品集状态组合。
另外还可以继续扩展,比如使用工厂模式来生产不同的状态机实现类或者再抽象一层,生产不同的产品。
大家可以扩散一下思维,欢迎来讨论和指点!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)