设计模式之责任链模式

本文详细介绍了责任链模式的概念,如何通过任务分解实现解耦和高内聚,提供了一个Java示例,展示了如何创建抽象类、具体任务类和责任链管理类。同时提到在大量子任务时使用线程池提高效率,并总结了模式的核心思想和使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 什么是责任链模式?

顾名思义,通过将一个操作划分为不同的责任(职责、任务),通过任务执行先后顺序,将每个任务串联起来形成一个链路模式。调用方不需要关注每个任务的具体实现,每个任务之间互相解耦,只需要关注自身任务即可。

2. 为什么用责任链模式?

使用责任链模式,可以将业务解耦,实现高内聚低耦合,提高代码可读性,只需要关注每个任务自身,维护成本低。

3. 责任链模式怎么用?

  1. 定义责任链基类
public abstract class TaskHandler {
    private List<TaskHandler> nexts;

    public void setNexts(List<TaskHandler> nexts) {
        this.nexts = nexts;
    }
    public List<TaskHandler> getNexts() {
        return nexts;
    }
    public abstract void handleRequest(TaskContext contextData);
    /**
     * @description: 当前职责的下游处理器
     **/
    public void syncNextHandler(List<TaskHandler> nexts, TaskContext contextData){
        if (ObjectUtils.isEmpty(nexts) || !contextData.isTaskStatus()) {
            return;
        }
        for (TaskHandler next : nexts){
            if(next == null){
                continue;
            }
            next.handleRequest(contextData);
        }
    }
}
  1. 定义每个任务的具体实现,根据业务需求,拆解任务
@Slf4j
public class Task extends TaskHandler{
    @Override
    public void handleRequest(TaskContext contextData) {
        try {
            log.info("开始执行责任链");
            System.out.println("开始执行责任链");
            contextData.setTaskCurNum(contextData.getTaskCurNum() +1);
        }catch (Exception e) {
            contextData.setTaskStatus(false);
            log.error("开始执行责任链:", e);
        }
        super.syncNextHandler(this.getNexts(), contextData);
    }
}
@Slf4j
public class Task1 extends TaskHandler{
    @Override
    public void handleRequest(TaskContext contextData) {
        try {
            log.info("执行任务1:");
            System.out.println("执行任务1");
            contextData.setTaskCurNum(contextData.getTaskCurNum() +1);
        }catch (Exception e) {
            contextData.setTaskStatus(false);
            log.error("执行任务1失败:", e);
        }
        super.syncNextHandler(this.getNexts(), contextData);
    }
}
  1. 定义责任链管理类,组装责任链所有任务
public class TaskChainMgt {
    private TaskHandler getTaskChain() {
        TaskHandler task1_1 = new Task1_1();
        TaskHandler task1_2 = new Task1_2();
        TaskHandler task1 = new Task1();
        task1.setNexts(Lists.newArrayList(task1_1, task1_2));
        TaskHandler task2 = new Task2();
        TaskHandler task = new Task();
        task.setNexts(Lists.newArrayList(task1, task2));
        return task;
    }
    // 启动责任链
    public void startTaskChain(TaskContext taskContext) {
        TaskHandler taskHandler = getTaskChain();
        taskHandler.handleRequest(taskContext);
    }
}
  1. 运行测试
@RestController
@Slf4j
@RequestMapping(value = "/taskChain")
public class TaskChainController {
    @GetMapping("/startTask")
    public void startTask() {
        TaskChainMgt taskChainMgt = new TaskChainMgt();
        TaskContext taskContext = new TaskContext();
        taskContext.setTaskTotalNum(5);
        taskChainMgt.startTaskChain(taskContext);
        boolean taskStatus = calTaskStatus(taskContext);
        if (taskStatus) {
            log.info("责任链执行结束");
        } else {
            log.error("责任链调用失败");
        }
    }
    /**
     * @Description: 轮询监听责任链执行结果
     **/
    private boolean calTaskStatus(TaskContext taskContext) {
        Long startTime = System.currentTimeMillis();
        boolean taskStatus = false;
        try {
            do{
                if (!taskContext.isTaskStatus()) {
                    log.error("责任链调度失败,上下文:{}", taskContext);
                    return false;
                }
                taskStatus = taskContext.getTaskCurNum() != taskContext.getTaskTotalNum();
                if((System.currentTimeMillis() - startTime)/1000>15){
                    log.error("责任链调度失败", taskContext);
                    return false;
                }
                if(taskStatus){
                    Thread.sleep(500);
                }
            }while (taskStatus);
            taskStatus = true;
        } catch (Exception e) {
            log.error("责任链异常!");
        }
        return taskStatus;
    }
}
2023-08-11 18:05:49.759  INFO 45648 --- [nio-8080-exec-1] c.e.f.d.t.t.Task                         : 开始执行责任链
开始执行责任链
2023-08-11 18:05:49.759  INFO 45648 --- [nio-8080-exec-1] c.e.f.d.t.t.Task1                        : 执行任务1:
执行任务1
2023-08-11 18:05:49.759  INFO 45648 --- [nio-8080-exec-1] c.e.f.d.t.t.Task1_1                      : 执行任务1_1:
执行任务1下子任务1_1
2023-08-11 18:05:49.759  INFO 45648 --- [nio-8080-exec-1] c.e.f.d.t.t.Task1_2                      : 执行任务1_2:
执行任务1下子任务1_2
2023-08-11 18:05:49.759  INFO 45648 --- [nio-8080-exec-1] c.e.f.d.t.t.Task2                        : 执行任务2:
执行任务2
2023-08-11 18:05:49.759  INFO 45648 --- [nio-8080-exec-1] c.e.f.c.TaskChainController              : 责任链执行结束

4. 扩展

如果任务下nexts子任务较多的情况下,可以使用线程池,多线程处理,提高责任链执行效率。

5. 总结

责任链模式设计思路主要通过设置nexts属性将所有任务串联起来形成一个链条,通过调用最顶层任务,每个任务执行完成后,获取当前任务的子任务(nexts),遍历执行每个子任务,子任务执行完成后,再执行子任务下的子任务…直到所有任务执行完毕。使用过程中可以使用全局上下文对象,用来在每个任务之间传递内容。使用轮询监听任务是否执行完毕。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值