责任链模式(Chain of Responsibility Pattern)

责任链模式(Chain of Responsibility Pattern)

责任链模式是一种行为型设计模式,它允许将请求沿着处理者链进行传递。每个处理者都可以对请求进行处理,或者将其传递给链中的下一个处理者。责任链模式通过将多个处理者连接成一条链,使得请求可以在链中传递,直到某个处理者处理它为止。

模式结构

  1. 处理者接口(Handler)
    定义处理请求的接口,通常包含一个处理请求的方法和一个设置下一个处理者的方法。
  2. 具体处理者(Concrete Handler)
    实现处理者接口,负责处理请求。如果当前处理者无法处理请求,则将其传递给链中的下一个处理者。
  3. 调用者(Client)
    创建责任链,并将请求发送给链中的第一个处理者。

代码示例

1. 处理者接口(Handler)

// 处理者接口:定义处理请求的接口
abstract class Middleware {
    private Middleware next;

    // 设置下一个处理者
    public Middleware linkWith(Middleware next) {
        this.next = next;
        return next;
    }

    // 处理请求的方法
    public abstract Boolean check(String name, String password);

    // 将请求传递给下一个处理者
    protected Boolean checkNext(String name, String password) {
        if (next == null) {
            return true;
        }
        return next.check(name, password);
    }
}

2. 具体处理者(Concrete Handler)

// 具体处理者:限制流量
class ThrottlingMiddleware extends Middleware {
    private final int requestPerMinute;
    private int request;
    private long currentTime;

    public ThrottlingMiddleware(int requestPerMinute) {
        this.requestPerMinute = requestPerMinute;
        this.currentTime = System.currentTimeMillis();
    }

    @Override
    public Boolean check(String name, String password) {
        if (System.currentTimeMillis() > currentTime + 60_000) {
            request = 0;
            currentTime = System.currentTimeMillis();
        }

        request++;
        if (request > requestPerMinute) {
            System.out.println("请求次数超过限制.");
            return false;
        }

        return checkNext(name, password);
    }
}

// 具体处理者:检查用户是否存在
class UserExistsMiddleware extends Middleware {
    private final Server server;

    public UserExistsMiddleware(Server server) {
        this.server = server;
    }

    @Override
    public Boolean check(String user, String password) {
        if (!server.hasUser(user)) {
            System.out.println("该用户未注册!");
            return false;
        }

        if (!server.isValidPassword(user, password)) {
            System.out.println("密码错误!");
            return false;
        }

        return checkNext(user, password);
    }
}

// 具体处理者:检查用户角色
class RoleCheckMiddleware extends Middleware {
    @Override
    public Boolean check(String user, String password) {
        if ("root".equals(user) || "admin".equals(user)) {
            System.out.println("Hello admin!");
            return true;
        }

        System.out.println("Hello user!");
        return checkNext(user, password);
    }
}

3.示例代码

public class ChainOfResponsibilityPattern {
    private static Server server;

    private static void init() {
        server = new Server();
        server.register("admin", "admin");
        server.register("root", "admin");
        server.register("jack", "heel");

        // 创建责任链
        Middleware middleware = new ThrottlingMiddleware(2);
        middleware.linkWith(new UserExistsMiddleware(server)).linkWith(new RoleCheckMiddleware());

        server.setMiddleware(middleware);
    }

    public static void main(String[] args) {
        init();

        boolean success;
        Scanner in = new Scanner(System.in);
        do {
            System.out.print("Enter user :");
            String user = in.nextLine();
            System.out.print("Input password : ");
            String password = in.nextLine();

            success = server.login(user, password);

        } while (!success);
    }
}

输出结果

Enter user :admin
Input password : admin
Hello admin!
认证通过,用户登录成功!

应用场景

  1. 多条件处理
    当程序需要根据不同的条件处理请求,且请求的处理顺序和条件未知时,可以使用责任链模式。
  2. 动态处理顺序
    当需要在运行时动态调整处理者的顺序时,可以使用责任链模式。
  3. 解耦请求和处理者
    当需要将请求的发送者和处理者解耦时,可以使用责任链模式。

在Java中的应用

  • javax.servlet.Filter
    Java Servlet 中的过滤器链(Filter Chain)就是责任链模式的一个典型应用。每个过滤器都可以对请求进行处理,或者将其传递给下一个过滤器。
  • java.util.logging.Logger
    Java 的日志框架中,日志记录器(Logger)可以将日志消息传递给父记录器,形成一条责任链。

优缺点

优点

  1. 解耦请求和处理者
    责任链模式将请求的发送者和处理者解耦,使得请求可以在链中传递,直到某个处理者处理它。
  2. 动态调整处理顺序
    责任链模式允许在运行时动态调整处理者的顺序,增加了系统的灵活性。
  3. 单一职责原则
    每个处理者只负责处理自己关心的请求,符合单一职责原则。

缺点

  1. 请求可能未被处理
    如果责任链配置不当,请求可能会传递到链的末端而未被处理。
  2. 性能问题
    责任链模式可能会导致请求在链中传递多次,增加了系统的性能开销。

总结

责任链模式通过将多个处理者连接成一条链,使得请求可以在链中传递,直到某个处理者处理它为止。它适用于需要根据不同的条件处理请求的场景,尤其是在请求的处理顺序和条件未知时。尽管它可能会增加系统的复杂性,但其优点在于提高了代码的灵活性和可扩展性。在Java中,责任链模式广泛应用于Servlet过滤器和日志框架等场景。