Java设计模式-责任链模式

Java设计模式-责任链模式

责任链模式概述

设计模式(Design Pattern)是面向对象软件开发中经过验证的通用解决方案 ,用于解决特定场景下的高频问题。其本质是经验沉淀的代码设计模板,通过抽象和封装提高代码的可维护性、复用性和扩展性

我认为:设计模式是一类问题的通用解决方案。

设计模式按目的分类有三类

  • 创建型:控制对象创建过程
  • 结构型:优化类/对象的组合方式
  • 行为型:定义对象交互与职责分配

责任链模式就是其中的行为型的设计模式.

责任链模式简介

责任链模式

  • 责任链模式是一种行为型设计模式。

  • 通过将多个处理对象连接成链,允许请求沿链传递直至被处理。其核心在于解耦请求发送者与接收者,使多个对象都有机会处理请求,且处理路径由链结构动态决定

责任链模式的作用

  • 解耦性:请求者无需知道具体处理者,处理者无需知道请求来源
  • 动态扩展:运行时灵活增删处理节点或调整链顺序
  • 职责单一:每个处理者仅关注自身能处理的请求类型

责任链模式的应用场景

  • 日志处理系统(如本示例)

  • Web请求过滤链(Servlet Filter)

  • 审批流程(多级领导审批)

  • 异常处理机制(多层异常捕获)

课程目标

  • 理解责任链模式的核心思想和应用场景
  • 识别应用场景,独立实现责任链模式
  • 能够权衡模式的适用性

责任链模式的核心组件

角色职责

角色 职责 示例类名
Handler 定义处理请求的接口,维护处理链引用 Logger
ConcreteHandler 实现具体处理逻辑,决定是否传递请求 ConsoleHandler
Client 构建处理链并触发请求 LogManager

类图

implements implements implements next builds chain <<interface>> Handler +Handler next +handle(request) ConsoleHandler +handle(request) FileHandler +handle(request) EmailHandler +handle(request) LogManager +main()

传统设计方式 VS 责任链模式

案例需求

案例背景:实现一个日志处理责任链,下面是具体要求:

1、日志依次经过如下处理器

2、控制台输出:输出日志到控制台

3、文件存储:将Error级别日志写入到文件中

4、短信报警:当出现fatal级别日志时,发送短信通知

传统模式的实现

代码示例如下:

java 复制代码
// 传统日志处理(强耦合)
class Logger {
    public void log(String level, String message) {
        if ("CONSOLE".equals(level)) {
            System.out.println("控制台输出:" + message);
        } else if ("FILE".equals(level)) {
            // 写入文件逻辑
        } else if ("SMS".equals(level)) {
            // 发送短信逻辑
        }
    }
}

传统模式的缺陷

  1. 新增日志类型需修改原有代码(违反开闭原则)
  2. 处理逻辑高度耦合,难以动态调整顺序
  3. 无法灵活组合不同处理策略

责任链模式的实现

责任链模式将修补传统实现方式的缺陷。

代码示例如下:

java 复制代码
// 抽象处理器
abstract class Logger {
    protected Logger next;
    protected String level;

    public void setNext(Logger next) {
        this.next = next;
    }

    public void log(String msgLevel, String message) {
        if (this.level.compareTo(msgLevel) <= 0) {
            writeLog(message);
        }
        if (next != null) {
            next.log(msgLevel, message);
        }
    }

    abstract protected void writeLog(String message);
}

// 控制台处理器
class ConsoleHandler extends Logger {
    public ConsoleHandler() {
        this.level = "CONSOLE";
    }

    @Override
    protected void writeLog(String message) {
        System.out.println("[控制台] " + message);
    }
}

// 文件处理器
class FileHandler extends Logger {
    public FileHandler() {
        this.level = "ERROR";
    }

    @Override
    protected void writeLog(String message) {
        // 文件写入逻辑
        System.out.println("[文件] 写入ERROR日志:" + message);
    }
}

// 短信处理器
class SmsHandler extends Logger {
    public SmsHandler() {
        this.level = "FATAL";
    }

    @Override
    protected void writeLog(String message) {
        // 短信发送逻辑
        System.out.println("[短信] 发送FATAL报警:" + message);
    }
}

// 客户端
public class LogManager {
    public static void main(String[] args) {
        Logger console = new ConsoleHandler();
        Logger file = new FileHandler();
        Logger sms = new SmsHandler();

        // 构建责任链:控制台 → 文件 → 短信
        console.setNext(file);
        file.setNext(sms);

        // 触发日志处理
        console.log("INFO", "系统正常运行");
        console.log("ERROR", "数据库连接失败");
        console.log("FATAL", "服务器宕机");
    }
}

责任链模式的优势

  1. 灵活扩展:新增日志处理器无需修改现有代码
  2. 动态配置:可通过配置文件调整处理链顺序
  3. 职责清晰:每个处理器专注特定日志级别处理

责任链模式的局限

  1. 性能损耗:长链可能导致请求传递延迟
  2. 调试复杂:链式调用增加问题定位难度
  3. 可能遗漏:若链中无匹配处理器,请求将被丢弃

模式变体

  • 静态链:通过配置文件定义处理顺序
  • 责任树:树形结构支持并行处理分支
  • 异步链:结合消息队列实现异步处理

最佳实践

  • 控制链长度:建议不超过7个节点(米勒法则)
  • 默认处理器:链尾设置兜底处理器防止遗漏
  • 日志追踪:添加链路ID实现请求跟踪
  • 性能优化:高频场景使用责任树代替单链

总结

通过责任链模式,我们成功构建了一个可动态扩展的日志处理系统,完美诠释了"开闭原则"和"单一职责原则"的设计哲学。这种模式特别适合需要多级协作但又不希望耦合度过高的场景。