改单接口重构(以下皆为伪代码)
一.背景
当前调度改单接口逻辑混乱,一个方法里面针对订单的属性的修改包含十余处,内部逻辑强耦合在一起,职责分析不明确,不利于后续扩展.为了提高改单的效率和可维护性,我们决定将订单处理流程拆解成多个职责单一的实现类。每个实现类只负责处理订单的一个步骤,通过判断需要修改的属性来注册相应的处理器,最后滚动一遍处理所有需要修改的属性(类似于责任链模式),生成一个修改完成的订单实体。
二.流程拆解
目前调度改单接口修改的操作比较多,下面仅列举出部分操作
1.变更订单支付类型
2.添加出发日期
3.修改方案类型
4.修改订单套餐等级
三.伪代码
1.定义修改类型枚举
package com.ctrip.train.ctripgraborder.entity.bizentity.modifyorder;
/**
*@Author: ljm
*@Date: 2024/12/10 16:03
*@Version: v1.0.0
*@Description: 改单接口修改类型
**/
public enum ModifyOrderType {
/*
变更订单支付类型
*/
MODIFY_PAY_FLAG("变更订单支付类型"),
/*
修改方案
*/
MODIFY_PLANS("修改方案"),
/*
等级发生改变
*/
MODIFY_PACKAGE_LEVEL("修改订单套餐等级"),
ADD_NEW_DEPART_DATES("新增出发日期");
private String description;
public String getDescription() {
return description;
}
ModifyOrderType(String description) {
this.description = description;
}
}
2.定义接口
/**
*@Author: ljm
*@Date: 2024/12/10 16:23
*@Version: v1.0.0
*@Description:
**/
public interface IModifyOrderHandler {
/**
* @author ljm
* @date 18:54 2024/12/13
* @param context
* 处理
**/
void handle(ModifyOrderInfoContext context);
/**
* @author ljm
* @date 20:51 2024/12/10
* 获取处理类型
**/
ModifyOrderType getModifyOrderType();
}
3.实现
3.1 变更订单支付类型实现
/**
*@Author: ljm
*@Date: 2024/12/10 18:02
*@Version: v1.0.0
*@Description: 变更订单支付类型实现
**/
@Service
public class ModifyPayFlagHandler implements IModifyOrderHandler {
@Override
public void handle(ModifyOrderInfoContext context) {
// 业务处理
}
@Override
public ModifyOrderType getModifyOrderType() {
return ModifyOrderType.MODIFY_PAY_FLAG;
}
}
3.1 添加出发日期实现
/**
*@Author: ljm
*@Date: 2024/12/10 18:02
*@Version: v1.0.0
*@Description: 新增出发日期处理类
**/
@Service
public class AddNewDepartDatesHandler implements IModifyOrderHandler {
@Override
public void handle(ModifyOrderInfoContext context) {
//业务处理
}
@Override
public ModifyOrderType getModifyOrderType() {
return ModifyOrderType.ADD_NEW_DEPART_DATES;
}
}
3.3 修改方案类型实现
/**
*@Author: ljm
*@Date: 2024/12/10 18:02
*@Version: v1.0.0
*@Description:修改方案类型实现
**/
@Service
public class ModifyPlansHandler implements IModifyOrderHandler {
@Override
public void handle(ModifyOrderInfoContext context) {
}
@Override
public ModifyOrderType getModifyOrderType() {
return ModifyOrderType.MODIFY_PLANS;
}
}
3.4 修改订单套餐等级实现
/**
*@Author: ljm
*@Date: 2024/12/10 18:02
*@Version: v1.0.0
*@Description: 修改订单套餐等级
**/
@Service
public class ModifyPackageLevelHandler implements IModifyOrderHandler {
@Override
public void handle(ModifyOrderInfoContext context) {
updatePackageLevel(context.getRequest(), context.getOriginOrder(), context.getOrderForUpdate());
}
@Override
public ModifyOrderType getModifyOrderType() {
return ModifyOrderType.MODIFY_PACKAGE_LEVEL;
}
}
4.定义handler执行器
/**
*@Author: ljm
*@Date: 2024/12/10 16:25
*@Version: v1.0.0
*@Description: 改单Handler处理
**/
@Service
public class ModifyOrderHandlerExecution {
private Map<ModifyOrderType, IModifyOrderHandler> HANDLER_MAP = new HashMap<>();
@Autowired
public ModifyOrderHandlerExecution(List<IModifyOrderHandler> updateOrderHandlers) {
updateOrderHandlers.forEach(x -> HANDLER_MAP.put(x.getModifyOrderType(), x));
}
/**
* @author ljm
* @date 18:09 2024/12/10
* @param modifyOrderTypeList
* @param context
* 根据处理类型循环处理,需要注意先后顺序, 如果A依赖B的结果, 添加的时候就需要先添加A再添加B!
**/
public void process(List<ModifyOrderType> modifyOrderTypeList, ModifyOrderInfoContext context) {
if (CollectionUtils.isEmpty(modifyOrderTypeList)) {
logger.warn("UpdateOrderHandlerExecution", "handlerTypes is Empty");
return;
}
// 循环处理
for (ModifyOrderType modifyOrderType : modifyOrderTypeList) {
IModifyOrderHandler iModifyOrderHandler = HANDLER_MAP.get(modifyOrderType);
iModifyOrderHandler.handle(context);
}
}
/**
* @author ljm
* @date 18:09 2024/12/10
* @param
* @param context
* 处理单个类型
**/
public void process(ModifyOrderType modifyOrderType, ModifyOrderInfoContext context) {
process(List.of(modifyOrderType), context);
}
/**
* @author ljm
* @date 18:17 2024/12/10
* @param context
* @return java.util.List<com.ctrip.train.ctripgraborder.business.service.updateorder.bean.UpdateOrderType>
* 获取改单需要修改哪些操作
**/
public List<ModifyOrderType> getModifyOrderTypeList(ModifyOrderInfoContext context) {
List<ModifyOrderType> modifyOrderTypeList = new ArrayList<>();
if (变更订单支付类型) {
modifyOrderTypeList.add(ModifyOrderType.MODIFY_PAY_FLAG);
}
if (修改方案) {
modifyOrderTypeList.add(ModifyOrderType.MODIFY_PLANS);
}
if (修改订单套餐等级) {
modifyOrderTypeList.add(ModifyOrderType.MODIFY_PACKAGE_LEVEL);
}
// 新增日期不为空
if (添加出发日期) {
modifyOrderTypeList.add(ModifyOrderType.ADD_NEW_DEPART_DATES);
}
return modifyOrderTypeList;
}
}
5.处理改单
public Respone modifyOrderInfo(Request request) {
// 1.创建上下文
ModifyOrderInfoContext context = ModifyOrderInfoContext.create(request, originOrder, originOrderDetail);
//2. 获取需要修改的操作
List<ModifyOrderType> modifyOrderTypeList = modifyOrderHandlerExecution.getModifyOrderTypeList(context);
// 3.处理
modifyOrderHandlerExecution.process(updateOrderTypeList, context);
// 4.db事务
// 5.发送MQ事件
return response;
}
四.总结
通过将订单处理流程拆解成多个职责单一的实现类,并通过判断需要修改的属性来注册相应的处理器,可以提高代码的可维护性和扩展性。每个实现类只负责处理订单的一个步骤,整个流程通过这些类的滚动调用来完成订单的修改。这种设计模式有助于后续更好地管理和扩展改单处理流程。