常用的责任链模式执行Task

368 阅读4分钟

1 只有执行顺序不依赖返回值

对于有明确先后顺序的任务执行,最适合的设计模式通常是 职责链模式(Chain of Responsibility Pattern)Command Pattern,但在你的场景下,Pipeline 模式任务调度模式 可能更为合适。

1.1 Pipeline 模式

Pipeline 模式是指将一系列任务(Task)按照顺序链接起来,每个任务在完成后会将结果传递给下一个任务。这个模式非常适合处理一系列必须按顺序执行的操作。例如,你可以将任务分成一个个独立的步骤,每个步骤完成后,结果被传递到下一个步骤进行处理。

class Task {
    private String name;
    private Task nextTask;

    public Task(String name) {
        this.name = name;
    }

    public void setNextTask(Task nextTask) {
        this.nextTask = nextTask;
    }

    public void execute() {
        System.out.println("Executing " + name);
        if (nextTask != null) {
            nextTask.execute();
        }
    }

    public static void main(String[] args) {
        // 创建任务
        Task task1 = new Task("Task 1");
        Task task2 = new Task("Task 2");
        Task task3 = new Task("Task 3");

        // 设置任务顺序
        task1.setNextTask(task2);
        task2.setNextTask(task3);

        // 执行第一个任务,后续的任务会按顺序执行
        task1.execute();
    }
}

1.2 任务调度模式(Task Scheduling)

使用 DAG(有向无环图) 来处理复杂的任务依赖关系。

import java.util.ArrayList;
import java.util.List;

class Task {
    private String name;
    private List<Task> dependencies = new ArrayList<>();

    public Task(String name) {
        this.name = name;
    }

    public void addDependency(Task task) {
        dependencies.add(task);
    }

    public void execute() {
        for (Task task : dependencies) {
            task.execute();
        }
        System.out.println("Executing " + name);
    }

    public static void main(String[] args) {
        // 创建任务
        Task task1 = new Task("Task 1");
        Task task2 = new Task("Task 2");
        Task task3 = new Task("Task 3");
        Task task4 = new Task("Task 4");

        // 设置任务依赖关系
        task3.addDependency(task1);
        task3.addDependency(task2);
        task4.addDependency(task3);

        // 执行最终任务,自动处理依赖关系
        task4.execute();
    }
}

1.3 命令模式(Command Pattern)

命令模式将每个任务封装为命令对象,并可以通过命令队列管理任务执行。

// 命令接口
interface Command {
    void execute();
}

// 具体任务命令
class TaskCommand implements Command {
    private String name;

    public TaskCommand(String name) {
        this.name = name;
    }

    @Override
    public void execute() {
        System.out.println("Executing " + name);
    }
}

// 调度器,负责管理命令的执行
class TaskScheduler {
    private List<Command> taskQueue = new ArrayList<>();

    public void addTask(Command task) {
        taskQueue.add(task);
    }

    public void executeTasks() {
        for (Command task : taskQueue) {
            task.execute();
        }
    }

    public static void main(String[] args) {
        // 创建任务命令
        Command task1 = new TaskCommand("Task 1");
        Command task2 = new TaskCommand("Task 2");
        Command task3 = new TaskCommand("Task 3");

        // 调度器管理任务
        TaskScheduler scheduler = new TaskScheduler();
        scheduler.addTask(task1);
        scheduler.addTask(task2);
        scheduler.addTask(task3);

        // 执行任务
        scheduler.executeTasks();
    }
}

1.4 适用场景

  • Pipeline 模式: 适用于任务按固定顺序串行执行的场景。
  • 任务调度模式: 适用于任务间有复杂依赖关系的情况。
  • 命令模式: 适用于需要对任务执行进行精细控制的场景,比如支持撤销和重做。

这些模式都能在 Java 中轻松实现,具体使用哪一种模式取决于你的任务流程和复杂性

2 要求执行顺序依赖前一个返回值

如果后一个任务需要前一个任务的返回值,可以使用 Pipeline 模式任务调度模式 的一种变体,称为 管道过滤器模式(Pipeline Filter Pattern)任务链模式,其中每个任务可以将结果传递给下一个任务。

2.1 使用 Pipeline 模式处理任务返回值

// 定义一个接口,所有任务实现该接口
interface Task {
    // 执行任务,并将结果返回
    String execute(String input);
}

// 具体任务实现 Task 接口
class Task1 implements Task {
    @Override
    public String execute(String input) {
        String result = input + " -> Task1 processed";
        System.out.println(result);
        return result;
    }
}

class Task2 implements Task {
    @Override
    public String execute(String input) {
        String result = input + " -> Task2 processed";
        System.out.println(result);
        return result;
    }
}

class Task3 implements Task {
    @Override
    public String execute(String input) {
        String result = input + " -> Task3 processed";
        System.out.println(result);
        return result;
    }
}

// 管道类,负责执行一系列任务
class Pipeline {
    private List<Task> tasks = new ArrayList<>();

    public void addTask(Task task) {
        tasks.add(task);
    }

    public void execute(String input) {
        String result = input;
        for (Task task : tasks) {
            result = task.execute(result);
        }
    }

    public static void main(String[] args) {
        // 创建任务
        Task task1 = new Task1();
        Task task2 = new Task2();
        Task task3 = new Task3();

        // 设置任务顺序
        Pipeline pipeline = new Pipeline();
        pipeline.addTask(task1);
        pipeline.addTask(task2);
        pipeline.addTask(task3);

        // 执行任务链
        pipeline.execute("Initial Input");
    }
}

2.2 解释

  1. Task 接口:每个任务实现 execute 方法,接收一个 String input 参数并返回处理后的 String 结果。这样后一个任务就可以使用前一个任务的输出。
  2. Pipeline 类:持有一个 Task 列表,按顺序执行每个任务,并将前一个任务的输出作为输入传递给下一个任务。
  3. 任务类(如 Task1, Task2, Task3):这些类实现了 Task 接口,定义了各自的业务逻辑。

2.3 运行示例

在上述代码中,Pipelineexecute 方法执行任务链,将每个任务的输出作为下一个任务的输入,并在控制台输出执行结果。例如:

Initial Input -> Task1 processed
Initial Input -> Task1 processed -> Task2 processed
Initial Input -> Task1 processed -> Task2 processed -> Task3 processed

这种模式适合处理需要依赖前一个任务的返回值的场景,确保任务按顺序执行,并正确传递中间结果。