设计模式探索:责任链模式

1. 什么是责任链模式

责任链模式 (Chain of Responsibility Pattern) 是一种行为型设计模式。定义如下:

  • 避免将一个请求的发送者与接收者耦合在一起,让多个对象都有机会处理请求。
  • 将接收请求的对象连接成一条链,并且沿着这条链传递请求,直到有一个对象能够处理它为止。

2. 责任链模式的作用

  • 将请求和请求的处理进行解耦,提高代码的可扩展性。

3. 责任链模式的结构

责任链模式主要包含以下角色:

  • 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接(链上的每个处理者都有一个成员变量来保存对于下一处理者的引用)。
  • 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
  • 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

在实际开发中,责任链模式可能会增加一个责任链管理者来管理具体的处理者。

4. 责任链模式在实际开发中的应用

在 SpringBoot 中,责任链模式的实践方式有多种,以下是一种示例:一个下单流程的多个独立检查逻辑。

4.1 实现方式1
  1. 创建 Pojo, 下单对象
java 复制代码
public class OrderContext {
    private String seqId;
    private String userId;
    private Long skuId;
    private Integer amount;
    private String userAddressId;
    // Getters and setters
}
  1. 创建处理者接口
java 复制代码
public interface OrderHandleIntercept {
    int sort();
    OrderContext handle(OrderContext context);
}
  1. 创建具体处理者类
java 复制代码
@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;
    }
}
  1. 处理器链类
java 复制代码
@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;
    }
}
  1. 进行单元测试
java 复制代码
@Autowired
private OrderHandleChainService orderHandleChainService;

@Test
public void test02() {
    orderHandleChainService.execute(new OrderContext());
}
  1. 执行结果

    通过seqId,检查客户是否重复下单
    检查请求参数是否合法,并且获取客户的银行账户
    检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额

4.2 实现方式2

通过注解 @Order 来指定排序

java 复制代码
@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

java 复制代码
@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

通过定义抽象类来实现责任链设计模式

java 复制代码
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;
    }
}

分别创建处理类

java 复制代码
@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;
    }
}

创建一个责任链管理器

java 复制代码
@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;
    }
}

测试

java 复制代码
@Autowired
private OrderHandleManager orderHandleManager;

@Test
public void test02() {
    orderHandleManager.execute(new OrderContext());
}

运行结果与预期一致:

复制代码
通过seqId,检查客户是否重复下单
检查请求参数,是否合法,并且获取客户的银行账户
检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额

5. 职责链模式总结

职责链模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许多个对象处理同一个请求,从而避免请求的发送者和接收者之间的耦合关系。这种模式为请求的处理提供了一条清晰的链,每个对象可以决定是否处理该请求或者将请求转发给链中的下一个对象。

职责链模式的优点:

  1. 降低耦合度:发送者和接收者之间没有直接的联系,降低了系统组件之间的耦合度。
  2. 增强灵活性:可以在运行时动态地添加或移除职责链中的处理对象,提高了系统的灵活性和可扩展性。
  3. 明确责任分配:每个处理对象只关注自己的职责范围,责任分配更加明确。

职责链模式的缺点:

  1. 请求处理不确定性:不能保证请求一定会被处理,如果链中的所有对象都不处理请求,请求将被忽略。
  2. 系统性能影响:请求可能需要通过较长的链进行传递,可能会对性能产生影响。
  3. 客户端复杂性增加:客户端可能需要了解整个职责链的配置,增加了客户端的使用复杂性。

职责链模式的使用场景:

  1. 多个对象处理请求:当一个请求需要多个对象依次处理时,可以使用职责链模式。
  2. 处理逻辑不明确:在运行时根据请求的类型动态选择处理对象,不希望客户端知道具体的处理逻辑。

职责链模式的实现可以通过组合多个具体处理者对象,并设置它们的后继者,形成一个处理链。当请求发出时,链中的每个对象依次判断是否能够处理该请求,如果可以处理则执行处理操作,否则将请求转发给链中的下一个对象。

这种模式在实际应用中非常广泛,例如在GUI应用程序的事件处理、工作流审批流程、过滤器链等场景中都有应用。通过使用职责链模式,可以提高系统的模块化和灵活性,同时降低组件之间的依赖关系。

相关推荐
杨充20 小时前
10.可测试性实战设计
设计模式·开源·代码规范
杨充20 小时前
9.重构十二式的实战
设计模式·开源·代码规范
杨充20 小时前
6.设计原则的全景图
设计模式·开源·全栈
杨充20 小时前
2.面向对象的特性
设计模式
杨充20 小时前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充20 小时前
8.反模式与坏味道
设计模式·开源·代码规范
杨充20 小时前
3.接口vs抽象类比较
设计模式
咖啡八杯1 天前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法
咖啡八杯1 天前
GoF设计模式——解释器模式
java·后端·spring·设计模式