1. 什么是责任链模式
责任链模式 (Chain of Responsibility Pattern) 是一种行为型设计模式。定义如下:
- 避免将一个请求的发送者与接收者耦合在一起,让多个对象都有机会处理请求。
- 将接收请求的对象连接成一条链,并且沿着这条链传递请求,直到有一个对象能够处理它为止。
2. 责任链模式的作用
- 将请求和请求的处理进行解耦,提高代码的可扩展性。
3. 责任链模式的结构
责任链模式主要包含以下角色:
- 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接(链上的每个处理者都有一个成员变量来保存对于下一处理者的引用)。
- 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
- 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
在实际开发中,责任链模式可能会增加一个责任链管理者来管理具体的处理者。
4. 责任链模式在实际开发中的应用
在 SpringBoot 中,责任链模式的实践方式有多种,以下是一种示例:一个下单流程的多个独立检查逻辑。
4.1 实现方式1
- 创建 Pojo, 下单对象
public class OrderContext {
private String seqId;
private String userId;
private Long skuId;
private Integer amount;
private String userAddressId;
// Getters and setters
}
- 创建处理者接口
public interface OrderHandleIntercept {
int sort();
OrderContext handle(OrderContext context);
}
- 创建具体处理者类
@Component
public class RepeatOrderHandleInterceptService implements OrderHandleIntercept {
@Override
public int sort() {
return 1; // 执行顺序为 1
}
@Override
public OrderContext handle(OrderContext context) {
System.out.println("通过seqId,检查客户是否重复下单");
return context;
}
}
@Component
public class ValidOrderHandleInterceptService implements OrderHandleIntercept {
@Override
public int sort() {
return 2; // 执行顺序为 2
}
@Override
public OrderContext handle(OrderContext context) {
System.out.println("检查请求参数是否合法,并且获取客户的银行账户");
return context;
}
}
@Component
public class BankOrderHandleInterceptService implements OrderHandleIntercept {
@Override
public int sort() {
return 3; // 执行顺序为 3
}
@Override
public OrderContext handle(OrderContext context) {
System.out.println("检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额");
return context;
}
}
- 处理器链类
@Component
public class OrderHandleChainService implements ApplicationContextAware {
private List<OrderHandleIntercept> handleList = new ArrayList<>();
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Map<String, OrderHandleIntercept> serviceMap = applicationContext.getBeansOfType(OrderHandleIntercept.class);
handleList = serviceMap.values().stream()
.sorted(Comparator.comparing(OrderHandleIntercept::sort))
.collect(Collectors.toList());
}
public OrderContext execute(OrderContext context) {
for (OrderHandleIntercept handleIntercept : handleList) {
context = handleIntercept.handle(context);
}
return context;
}
}
- 进行单元测试
@Autowired
private OrderHandleChainService orderHandleChainService;
@Test
public void test02() {
orderHandleChainService.execute(new OrderContext());
}
- 执行结果
通过seqId,检查客户是否重复下单
检查请求参数是否合法,并且获取客户的银行账户
检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额
4.2 实现方式2
通过注解 @Order 来指定排序
@Order(1)
@Component
public class RepeatOrderHandleInterceptService implements OrderHandleIntercept {
//...省略
}
@Order(2)
@Component
public class ValidOrderHandleInterceptService implements OrderHandleIntercept {
//...省略
}
@Order(3)
@Component
public class BankOrderHandleInterceptService implements OrderHandleIntercept {
//...省略
}
修改 OrderHandleChainService
@Component
public class OrderHandleChainService {
@Autowired
private List<OrderHandleIntercept> handleList;
public OrderContext execute(OrderContext context) {
for (OrderHandleIntercept handleIntercept : handleList) {
context = handleIntercept.handle(context);
}
return context;
}
}
4.3 实现方式3
通过定义抽象类来实现责任链设计模式
public abstract class AbstractOrderHandle {
private AbstractOrderHandle next;
public AbstractOrderHandle getNext() {
return next;
}
public void setNext(AbstractOrderHandle next) {
this.next = next;
}
public abstract OrderContext handle(OrderContext orderContext);
public OrderContext execute(OrderContext context) {
context = handle(context);
if (getNext() != null) {
getNext().execute(context);
}
return context;
}
}
分别创建处理类
@Component
@Order(1)
public class RepeatOrderHandle extends AbstractOrderHandle {
@Override
public OrderContext handle(OrderContext context) {
System.out.println("通过seqId,检查客户是否重复下单");
return context;
}
}
@Component
@Order(2)
public class ValidOrderHandle extends AbstractOrderHandle {
@Override
public OrderContext handle(OrderContext context) {
System.out.println("检查请求参数,是否合法,并且获取客户的银行账户");
return context;
}
}
@Component
@Order(3)
public class BankOrderHandle extends AbstractOrderHandle {
@Override
public OrderContext handle(OrderContext context) {
System.out.println("检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额");
return context;
}
}
创建一个责任链管理器
@Component
public class OrderHandleManager {
@Autowired
private List<AbstractOrderHandle> orderHandleList;
@PostConstruct
public void initChain() {
int size = orderHandleList.size();
for (int i = 0; i < size; i++) {
if (i == size - 1) {
orderHandleList.get(i).setNext(null);
} else {
orderHandleList.get(i).setNext(orderHandleList.get(i + 1));
}
}
}
public OrderContext execute(OrderContext context) {
OrderContext execute = orderHandleList.get(0).execute(context);
return context;
}
}
测试
@Autowired
private OrderHandleManager orderHandleManager;
@Test
public void test02() {
orderHandleManager.execute(new OrderContext());
}
运行结果与预期一致:
通过seqId,检查客户是否重复下单
检查请求参数,是否合法,并且获取客户的银行账户
检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额
5. 职责链模式总结
优点:
- 降低了对象之间的耦合。
- 增强了给对象委派职责的灵活性。
- 简化了对象之间的连接,责任分担更加明确。
缺点:
- 不能保证每个请求一定被处理。
- 系统性能可能会有影响。
- 增加了客户端的复杂性。
使用场景:
- 在运行时需要使用多个对象对一个请求进行处理。
- 不希望让使用者知道具体的处理逻辑。