责任链模式

发布时间:2023年12月17日

一、概念

责任链模式:将链中每个节点看成一个对象,每个节点处理一件事情,如果节点出现异常,则中断执行。

二、代码实践

首先,我们定义一个简易版的下单对象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<OrderHandleIntercept> handleList = new ArrayList<>();
 
 
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        //获取指定的接口实现类,并按照sort进行排序,放入List中
        Map<String, OrderHandleIntercept> 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<OrderHandleIntercept> 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;
    }
}
 

文章来源:https://blog.csdn.net/xuehuagongzi000/article/details/134956485
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。