行为型模式:责任链模式

发布于:2025-05-16 ⋅ 阅读:(7) ⋅ 点赞:(0)

什么是责任链模式

责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,它将请求的发送者和接收者解耦,允许多个对象都有机会处理请求。这些对象连接成一条链,请求沿着链传递,直到有对象处理它为止。

责任链模式的核心思想是:将能够处理同一类请求的对象连成一条链,请求沿着这条链传递,直到链上的某个对象能够处理该请求。这样可以避免请求发送者与接收者之间的耦合关系。

责任链模式的结构

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

  1. 处理者(Handler):定义一个处理请求的接口,通常包含对下一个处理者的引用
  2. 具体处理者(Concrete Handler):实现处理者接口,处理它负责的请求,可以访问下一个处理者
  3. 客户端(Client):创建处理链,并向链上的第一个处理者发送请求
«interface»
Handler
+setNext(handler: Handler)
+handle(request: Request)
ConcreteHandler1
-next: Handler
+setNext(handler: Handler)
+handle(request: Request)
ConcreteHandler2
-next: Handler
+setNext(handler: Handler)
+handle(request: Request)
ConcreteHandler3
-next: Handler
+setNext(handler: Handler)
+handle(request: Request)

责任链模式的基本实现

下面是责任链模式的基本Java实现:

// 请求类
class Request {
    private String type;
    private int amount;
    
    public Request(String type, int amount) {
        this.type = type;
        this.amount = amount;
    }
    
    public String getType() {
        return type;
    }
    
    public int getAmount() {
        return amount;
    }
}

// 处理者接口
interface Handler {
    Handler setNext(Handler handler);
    String handle(Request request);
}

// 抽象处理者类
abstract class AbstractHandler implements Handler {
    private Handler next;
    
    @Override
    public Handler setNext(Handler handler) {
        this.next = handler;
        return handler; // 返回下一个处理者,支持链式调用
    }
    
    @Override
    public String handle(Request request) {
        if (next != null) {
            return next.handle(request);
        }
        
        return "没有处理者可以处理该请求";
    }
}

// 具体处理者:经理
class ManagerHandler extends AbstractHandler {
    @Override
    public String handle(Request request) {
        if ("请假".equals(request.getType()) && request.getAmount() <= 3) {
            return "经理已批准请假申请";
        }
        
        // 不能处理,传递给下一个处理者
        return super.handle(request);
    }
}

// 具体处理者:总监
class DirectorHandler extends AbstractHandler {
    @Override
    public String handle(Request request) {
        if ("请假".equals(request.getType()) && request.getAmount() <= 7) {
            return "总监已批准请假申请";
        } else if ("经费".equals(request.getType()) && request.getAmount() <= 5000) {
            return "总监已批准经费申请";
        }
        
        // 不能处理,传递给下一个处理者
        return super.handle(request);
    }
}

// 具体处理者:CEO
class CEOHandler extends AbstractHandler {
    @Override
    public String handle(Request request) {
        if ("请假".equals(request.getType()) && request.getAmount() <= 14) {
            return "CEO已批准请假申请";
        } else if ("经费".equals(request.getType()) && request.getAmount() <= 50000) {
            return "CEO已批准经费申请";
        }
        
        // 不能处理,传递给下一个处理者
        return super.handle(request);
    }
}

// 客户端代码
public class ChainOfResponsibilityDemo {
    public static void main(String[] args) {
        // 创建处理链
        Handler manager = new ManagerHandler();
        Handler director = new DirectorHandler();
        Handler ceo = new CEOHandler();
        
        // 设置责任链
        manager.setNext(director).setNext(ceo);
        
        // 创建请求
        Request request1 = new Request("请假", 2);
        Request request2 = new Request("请假", 5);
        Request request3 = new Request("请假", 10);
        Request request4 = new Request("请假", 20);
        Request request5 = new Request("经费", 4000);
        Request request6 = new Request("经费", 20000);
        Request request7 = new Request("经费", 100000);
        
        // 处理请求
        System.out.println(manager.handle(request1)); // 经理处理
        System.out.println(manager.handle(request2)); // 总监处理
        System.out.println(manager.handle(request3)); // CEO处理
        System.out.println(manager.handle(request4)); // 无人处理
        System.out.println(manager.handle(request5)); // 总监处理
        System.out.println(manager.handle(request6)); // CEO处理
        System.out.println(manager.handle(request7)); // 无人处理
    }
}

实际应用示例:日志记录器

下面通过一个日志记录系统来展示责任链模式的实际应用:

// 日志级别枚举
enum LogLevel {
    INFO(1), DEBUG(2), ERROR(3);
    
    private int level;
    
    LogLevel(int level) {
        this.level = level;
    }
    
    public int getLevel() {
        return level;
    }
}

// 日志对象
class LogMessage {
    private LogLevel level;
    private String message;
    
    public LogMessage(LogLevel level, String message) {
        this.level = level;
        this.message = message;
    }
    
    public LogLevel getLevel() {
        return level;
    }
    
    public String getMessage() {
        return message;
    }
}

// 抽象日志处理器
abstract class LoggerHandler {
    protected LogLevel level;
    protected LoggerHandler next;
    
    public LoggerHandler(LogLevel level) {
        this.level = level;
    }
    
    // 设置下一个处理者
    public LoggerHandler setNext(LoggerHandler next) {
        this.next = next;
        return next;
    }
    
    // 处理日志消息
    public void log(LogMessage logMessage) {
        if (logMessage.getLevel().getLevel() >= this.level.getLevel()) {
            writeLog(logMessage);
        }
        
        if (next != null) {
            next.log(logMessage);
        }
    }
    
    // 由具体子类实现的写日志方法
    protected abstract void writeLog(LogMessage logMessage);
}

// 控制台日志处理器
class ConsoleLogger extends LoggerHandler {
    public ConsoleLogger(LogLevel level) {
        super(level);
    }
    
    @Override
    protected void writeLog(LogMessage logMessage) {
        System.out.println("控制台日志:" + logMessage.getLevel() + " - " + logMessage.getMessage());
    }
}

// 文件日志处理器
class FileLogger extends LoggerHandler {
    public FileLogger(LogLevel level) {
        super(level);
    }
    
    @Override
    protected void writeLog(LogMessage logMessage) {
        System.out.println("文件日志:" + logMessage.getLevel() + " - " + logMessage.getMessage());
    }
}

// 数据库日志处理器
class DatabaseLogger extends LoggerHandler {
    public DatabaseLogger(LogLevel level) {
        super(level);
    }
    
    @Override
    protected void writeLog(LogMessage logMessage) {
        System.out.println("数据库日志:" + logMessage.getLevel() + " - " + logMessage.getMessage());
    }
}

// 客户端代码
public class LoggerExample {
    public static void main(String[] args) {
        // 创建日志处理链
        LoggerHandler consoleLogger = new ConsoleLogger(LogLevel.INFO);
        LoggerHandler fileLogger = new FileLogger(LogLevel.DEBUG);
        LoggerHandler databaseLogger = new DatabaseLogger(LogLevel.ERROR);
        
        // 构建责任链
        consoleLogger.setNext(fileLogger).setNext(databaseLogger);
        
        // 创建日志消息
        LogMessage infoLog = new LogMessage(LogLevel.INFO, "这是一条信息日志");
        LogMessage debugLog = new LogMessage(LogLevel.DEBUG, "这是一条调试日志");
        LogMessage errorLog = new LogMessage(LogLevel.ERROR, "这是一条错误日志");
        
        // 处理日志
        System.out.println("=== 处理信息日志 ===");
        consoleLogger.log(infoLog);
        
        System.out.println("\n=== 处理调试日志 ===");
        consoleLogger.log(debugLog);
        
        System.out.println("\n=== 处理错误日志 ===");
        consoleLogger.log(errorLog);
    }
}

实际应用示例:Web请求过滤器

下面是一个Web请求过滤器的例子,类似于Java Servlet Filter:

// HTTP请求
class HttpRequest {
    private String requestBody;
    private Map<String, String> headers;
    private String ip;
    
    public HttpRequest(String ip, Map<String, String> headers, String requestBody) {
        this.ip = ip;
        this.headers = headers;
        this.requestBody = requestBody;
    }
    
    public String getRequestBody() {
        return requestBody;
    }
    
    public Map<String, String> getHeaders() {
        return headers;
    }
    
    public String getIp() {
        return ip;
    }
}

// HTTP响应
class HttpResponse {
    private int statusCode;
    private String body;
    
    public HttpResponse() {
        this.statusCode = 200;
        this.body = "";
    }
    
    public void setStatusCode(int statusCode) {
        this.statusCode = statusCode;
    }
    
    public void setBody(String body) {
        this.body = body;
    }
    
    @Override
    public String toString() {
        return "HttpResponse{" +
                "statusCode=" + statusCode +
                ", body='" + body + '\'' +
                '}';
    }
}

// 过滤器接口
interface Filter {
    void setNext(Filter filter);
    HttpResponse doFilter(HttpRequest request, HttpResponse response);
}

// 抽象过滤器
abstract class BaseFilter implements Filter {
    protected Filter next;
    
    @Override
    public void setNext(Filter filter) {
        this.next = filter;
    }
    
    @Override
    public HttpResponse doFilter(HttpRequest request, HttpResponse response) {
        // 如果有下一个过滤器,调用它
        if (next != null) {
            return next.doFilter(request, response);
        }
        return response;
    }
}

// IP黑名单过滤器
class IpBlacklistFilter extends BaseFilter {
    private List<String> blacklist = Arrays.asList("192.168.1.1", "10.0.0.1");
    
    @Override
    public HttpResponse doFilter(HttpRequest request, HttpResponse response) {
        if (blacklist.contains(request.getIp())) {
            response.setStatusCode(403);
            response.setBody("IP被禁止访问");
            return response;
        }
        
        return super.doFilter(request, response);
    }
}

// 认证过滤器
class AuthenticationFilter extends BaseFilter {
    @Override
    public HttpResponse doFilter(HttpRequest request, HttpResponse response) {
        if (!request.getHeaders().containsKey("Authorization")) {
            response.setStatusCode(401);
            response.setBody("需要认证");
            return response;
        }
        
        return super.doFilter(request, response);
    }
}

// 内容类型过滤器
class ContentTypeFilter extends BaseFilter {
    @Override
    public HttpResponse doFilter(HttpRequest request, HttpResponse response) {
        if (!request.getHeaders().containsKey("Content-Type") || 
           !request.getHeaders().get("Content-Type").equals("application/json")) {
            response.setStatusCode(415);
            response.setBody("不支持的媒体类型");
            return response;
        }
        
        return super.doFilter(request, response);
    }
}

// 日志过滤器
class LoggingFilter extends BaseFilter {
    @Override
    public HttpResponse doFilter(HttpRequest request, HttpResponse response) {
        System.out.println("请求IP: " + request.getIp());
        System.out.println("请求头: " + request.getHeaders());
        
        HttpResponse processedResponse = super.doFilter(request, response);
        
        System.out.println("响应状态码: " + processedResponse.toString());
        return processedResponse;
    }
}

// Web应用
class WebApplication {
    private Filter filterChain;
    
    public WebApplication(Filter filterChain) {
        this.filterChain = filterChain;
    }
    
    public HttpResponse handleRequest(HttpRequest request) {
        HttpResponse response = new HttpResponse();
        
        // 执行过滤器链
        response = filterChain.doFilter(request, response);
        
        // 如果请求通过所有过滤器,设置成功响应
        if (response.toString().contains("statusCode=200")) {
            response.setBody("请求处理成功");
        }
        
        return response;
    }
}

// 客户端代码
public class WebFilterExample {
    public static void main(String[] args) {
        // 创建过滤器
        Filter loggingFilter = new LoggingFilter();
        Filter ipFilter = new IpBlacklistFilter();
        Filter authFilter = new AuthenticationFilter();
        Filter contentTypeFilter = new ContentTypeFilter();
        
        // 设置过滤器链
        loggingFilter.setNext(ipFilter);
        ipFilter.setNext(authFilter);
        authFilter.setNext(contentTypeFilter);
        
        // 创建Web应用
        WebApplication app = new WebApplication(loggingFilter);
        
        // 测试不同请求
        Map<String, String> headers1 = new HashMap<>();
        HttpRequest request1 = new HttpRequest("192.168.1.1", headers1, "");
        
        Map<String, String> headers2 = new HashMap<>();
        HttpRequest request2 = new HttpRequest("192.168.1.2", headers2, "");
        
        Map<String, String> headers3 = new HashMap<>();
        headers3.put("Authorization", "Bearer token123");
        HttpRequest request3 = new HttpRequest("192.168.1.2", headers3, "");
        
        Map<String, String> headers4 = new HashMap<>();
        headers4.put("Authorization", "Bearer token123");
        headers4.put("Content-Type", "application/json");
        HttpRequest request4 = new HttpRequest("192.168.1.2", headers4, "{\"key\":\"value\"}");
        
        // 处理请求
        System.out.println("=== 请求1: 黑名单IP ===");
        System.out.println(app.handleRequest(request1));
        
        System.out.println("\n=== 请求2: 未认证 ===");
        System.out.println(app.handleRequest(request2));
        
        System.out.println("\n=== 请求3: 缺少Content-Type ===");
        System.out.println(app.handleRequest(request3));
        
        System.out.println("\n=== 请求4: 有效请求 ===");
        System.out.println(app.handleRequest(request4));
    }
}

责任链模式在Java API中的应用

Java API中有多个使用责任链模式的例子:

  1. java.util.logging.Logger:日志记录器采用了责任链模式,消息沿着Logger层次结构传递。

  2. javax.servlet.Filter:Java Servlet中的过滤器链,HTTP请求依次经过一系列过滤器处理。

  3. java.awt.Container#dispatchEvent():事件处理中,事件沿着组件层次结构传递。

责任链模式的优点

  1. 降低耦合度:请求发送者与接收者解耦,发送者无需知道谁会处理请求。

  2. 增强灵活性:可以动态地添加、删除或重新排序处理者,而不影响客户端代码。

  3. 符合单一职责原则:每个处理者只关注自己能处理的请求类型。

  4. 符合开闭原则:无需修改现有代码即可添加新的处理者。

  5. 可以实现不同的处理方式:请求可以由一个处理者处理或多个处理者部分处理。

责任链模式的缺点

  1. 请求可能没有处理者:如果链末尾没有合适的处理者,请求可能未被处理。

  2. 性能问题:请求可能要遍历整条链才能找到合适的处理者。

  3. 调试困难:请求在链中的行为路径不易跟踪,增加了调试难度。

  4. 可能的递归调用:处理者之间的递归调用可能导致栈溢出。

责任链模式与其他模式的比较

责任链 vs 命令模式

  • 责任链模式:专注于请求的传递和处理,接收者可能有多个。
  • 命令模式:将请求封装为对象,关注请求的发送者和接收者之间的解耦。

责任链 vs 装饰器模式

  • 责任链模式:每个处理者决定是否处理请求或传递给下一个处理者。
  • 装饰器模式:每个装饰器都会处理请求,然后将其传递给下一个组件。

责任链模式的变体

1. 纯责任链

每个处理者要么完全处理请求,要么将请求完全传递给下一个处理者:

// 纯责任链处理者
interface PureHandler {
    boolean handle(Request request);
    void setNext(PureHandler handler);
}

2. 带回调的责任链

处理完成后调用回调方法:

// 带回调的处理者
interface CallbackHandler {
    void handle(Request request, Callback callback);
}

// 回调接口
interface Callback {
    void onSuccess(String result);
    void onFailure(String error);
}

最佳实践和注意事项

  1. 合理设置处理顺序:将常用或简单的处理者放在链的前面,提高效率。

  2. 设置默认处理者:确保链末尾有默认处理者,避免请求未处理。

  3. 警惕处理循环:确保责任链中不会出现循环引用。

  4. 避免过长的责任链:过长的链会影响性能和可维护性。

  5. 考虑链的动态性:在某些情况下,可能需要动态修改责任链。

  6. 明确终止条件:每个处理者应明确何时停止处理,何时传递请求。

总结

责任链模式是一种强大的行为设计模式,它允许多个对象处理同一个请求,而发送者无需知道具体的处理者。通过将对象连成一条链,并沿着链传递请求,直到有对象能够处理它为止,责任链模式提供了一种灵活且松耦合的解决方案。

这种模式在需要按特定顺序处理请求,或者不确定由哪个对象处理请求的场景中非常有用。它广泛应用于日志记录、错误处理、请求过滤、事件处理等多种场景。

虽然责任链模式有可能导致请求未被处理或性能问题,但通过合理设计和使用,这些缺点是可以避免的。在复杂的系统中,责任链模式是实现灵活处理流程的有效工具。