责任链模式:将链中每个节点看成一个对象,每个节点处理一件事情,如果节点出现异常,则中断执行。
首先,我们定义一个简易版的下单对象OrderContext
。
public class OrderContext {
/**
* 请求唯一序列ID
*/
private String seqId;
/**
* 用户ID
*/
private String userId;
/**
* 产品skuId
*/
private Long skuId;
/**
* 下单数量
*/
private Integer amount;
/**
* 用户收货地址ID
*/
private String userAddressId;
//..set、get
}
然后,我们定义一个数据处理接口OrderHandleIntercept
,用于标准化执行!
public interface OrderHandleIntercept {
/**
* 指定执行顺序
* @return
*/
int sort();
/**
* 对参数进行处理
* @param context
* @return
*/
OrderAddContext handle(OrderAddContext context);
}
接着,我们分别创建三个不同的接口实现类,并指定执行顺序,内容如下:
RepeatOrderHandleInterceptService:用于重复下单的逻辑验证
ValidOrderHandleInterceptService:用于验证请求参数是否合法
BankOrderHandleInterceptService:用于检查客户账户余额是否充足
@Component
public class RepeatOrderHandleInterceptService implements OrderHandleIntercept {
@Override
public int sort() {
//用于重复下单的逻辑验证,在执行顺序为1
return 1;
}
@Override
public OrderAddContext handle(OrderAddContext context) {
System.out.println("通过seqId,检查客户是否重复下单");
return context;
}
}
@Component
public class ValidOrderHandleInterceptService implements OrderHandleIntercept {
@Override
public int sort() {
//用于验证请求参数是否合法,执行顺序为2
return 2;
}
@Override
public OrderAddContext handle(OrderAddContext context) {
System.out.println("检查请求参数,是否合法,并且获取客户的银行账户");
return context;
}
}
@Component
public class BankOrderHandleInterceptService implements OrderHandleIntercept {
@Override
public int sort() {
//用于检查客户账户余额是否充足,在执行顺序为3
return 3;
}
@Override
public OrderAddContext handle(OrderAddContext context) {
System.out.println("检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额");
return context;
}
}
再然后,我们还需要创建一个订单数据验证管理器OrderHandleChainService
,用于管理这些实现类。
@Component
public class OrderHandleChainService implements ApplicationContextAware {
private List handleList = new ArrayList<>();
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//获取指定的接口实现类,并按照sort进行排序,放入List中
Map serviceMap = applicationContext.getBeansOfType(OrderHandleIntercept.class);
handleList = serviceMap.values().stream()
.sorted(Comparator.comparing(OrderHandleIntercept::sort))
.collect(Collectors.toList());
}
/**
* 执行处理
* @param context
* @return
*/
public OrderAddContext execute(OrderAddContext context){
for (OrderHandleIntercept handleIntercept : handleList) {
context =handleIntercept.handle(context);
}
return context;
}
}
最后,我们编写单元测试来看看效果如何!
@RunWith(SpringRunner.class)
@SpringBootTest
public class CalculatorServiceTest {
@Autowired
private OrderHandleChainService orderHandleChainService;
@Test
public void test(){
orderHandleChainService.execute(new OrderAddContext());
}
}
执行结果如下:
通过seqId,检查客户是否重复下单
检查请求参数,是否合法,并且获取客户的银行账户
检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额
如果需要继续加验证流程或者处理流程,只需要重新实现OrderHandleIntercept
接口就行,其他的代码无需改动!
当然,有的同学可能觉得这种方法用的不习惯,不喜欢通过sort()
来指定顺序,也可以通过如下方式进行手动add
排序。
@Component
public class OrderHandleChainService {
private List handleList = new ArrayList<>();
@Autowired
private ValidOrderHandleInterceptService validOrderHandleInterceptService;
@Autowired
private RepeatOrderHandleInterceptService repeatOrderHandleInterceptService;
@Autowired
private BankOrderHandleInterceptService bankOrderHandleInterceptService;
@PostConstruct
public void init(){
//依次手动add对象
handleList.add(repeatOrderHandleInterceptService);
handleList.add(validOrderHandleInterceptService);
handleList.add(bankOrderHandleInterceptService);
}
/**
* 执行处理
* @param context
* @return
*/
public OrderAddContext execute(OrderAddContext context){
for (OrderHandleIntercept handleIntercept : handleList) {
context =handleIntercept.handle(context);
}
return context;
}
}