什么是责任链模式?

什么是责任链模式

在构建复杂系统时,我们常常面临这样的挑战: 一个请求或事件需要经过多个处理环节 ,这些环节可能动态变化,处理者在运行时才能确定。如何优雅地组织这些处理逻辑,避免代码陷入臃肿的"巨无霸方法"困境?

想象这样的场景:系统启动初始化流程需要依次执行用户初始化、展示数据加载、元数据配置和系统Banner展示等步骤。如果不用设计模式,代码往往沦为这样的"一坨":

public void initSystem() {
    // 初始化用户模块
    initUserService();
  
    // 加载展示数据
    loadDisplayData();
  
    // 配置元数据
    configureMetadata();
  
    // 展示系统Banner
    showStartupBanner();
  
    // 新增需求:添加系统监控
    initMonitoring(); // 每次新增都要修改这个核心方法!
  
    // 未来可能还要添加更多步骤...
}

这种实现存在三大痛点:

  1. 违反开闭原则 :每次新增初始化步骤都要修改initSystem()方法
  2. 耦合度高 :各步骤执行顺序硬编码在单一方法中
  3. 难以扩展 :无法动态调整处理流程(如跳过某些步骤)

责任链模式 (Chain of Responsibility) 正是解决这类问题的利器。它像搭建乐高积木一样,将处理步骤拆分为独立单元,通过链式连接实现灵活组装:

// 构建初始化责任链
InitializationChain chain = new InitializationChain();
chain.addHandler(new UserInitHandler())
     .addHandler(new DataLoadHandler())
     .addHandler(new MetadataHandler())
     .addHandler(new BannerHandler());

// 执行初始化流程
chain.execute();

当需要新增监控初始化时,只需:

chain.insertAfter(MetadataHandler.class, new MonitoringHandler());

无需触碰核心逻辑 ,系统初始化流程即刻升级。甚至可以做到热拔插不用停机也能更新升级!。

和策略模式的区别

很多人会把责任链和策略模式混淆,它们确实都强调“解耦逻辑”,但关注点不同:

模式 适用场景
策略模式 替代 if-else,根据条件选择一种处理方式
责任链模式 请求需要“多步处理”或“逐步接力”,处理器可能中断或放行请求传递

简言之:

  • 策略模式: 多选一。
  • 责任链模式: 多步走。

实战

FishPi-Pyclient

在摸鱼派的python客户端里也使用了责任链模式来进行初始化,也是为了方便拓展和可读性。
摸鱼派Python客户端的初始化逻辑可以理解为这样

InitChain
    调用 init() 初始化链
    append() 添加每个 Initor(节点)
Initor (抽象基类)
   ├── DefualtConfigInitor //生成默认配置
   ├── EnvConfigInitor      //从环境变量里读取配置并覆盖默认配置
   ├── FileConfigInitor      //从指定配置文件里读取配置并覆盖环境变量配置
   ├── CilConfigInitor       //从命令行启动参数里读取配置并覆盖配置文件里的配置
   ├── LoginInitor            //通过配置的参数登录摸鱼派
   ├── BoloLoginInitor     //如果填写了bolo账号密码,则进行bolo登录
   ├── ChaRoomInitor     //聊天室初始化
   └── CliInitor                 //命令行指令接收器初始化
def init(self):
    self.append(DefualtConfigInitor(),
                EnvConfigInitor(),
                FileConfigInitor(),
                CilConfigInitor(),
                LoginInitor(),
                BoloLoginInitor(),
                ChaRoomInitor(),
                CliInitor())
    self.head.init(self.api, self.options)

每个 Initor 通过 next 指向下一个处理节点,实现链式调用。新增或调整初始化步骤,仅需变动链的构造顺序,完全解耦逻辑与流程。

Netty

Netty中的 ChannelPipeline & ChannelHandler
Netty 作为高性能网络框架的标杆,其核心之一 ChannelPipeline 就是责任链模式的 教科书级应用

  • ChannelPipeline (管道): 这就是那条 责任链 。它管理着所有处理网络事件的 ChannelHandler,并定义了事件在链上 传播的规则 (入站事件从头到尾,出站事件从尾到头)。
  • ChannelHandler (处理器): 这就是链上的一个个 处理器 。分为两大类:
    • ChannelInboundHandler:处理 入站事件 (如连接建立channelActive、数据到达channelRead、异常发生exceptionCaught)。
    • ChannelOutboundHandler:处理 出站事件 (如连接请求connect、数据写出write、关闭连接close)。
  • ChannelHandlerContext (处理器上下文): 它封装了一个 ChannelHandler 及其在 Pipeline 中的位置信息。它是处理器 与链交互的桥梁 ,提供了:
    • 访问关联的 ChannelPipeline
    • 最重要的 fire* 方法 (如 fireChannelRead(Object msg)),用于 将事件传递给链中的下一个处理器
    • 读写操作等。

摸鱼派的web框架latke底层则是基于Netty实现的。

private void startServer(final SocketAddress socketAddress, final Class<? extends ServerChannel> channelClass) {
        try {
            InternalLoggerFactory.setDefaultFactory(Log4J2LoggerFactory.INSTANCE);
            new ServerBootstrap().
                    group(BOSS_GROUP, WORKER_GROUP).
                    channel(channelClass).
                    handler(new LoggingHandler(LogLevel.INFO)).
                    childHandler(new HttpServerInitializer()).
                    bind(socketAddress).sync().channel().closeFuture().sync();
        } catch (final Exception e) {
            LOGGER.log(Level.ERROR, "Start server failed, exit process", e);
            System.exit(-1);
        }
    }
private static final class HttpServerInitializer extends ChannelInitializer<Channel> {

    @Override
    public void initChannel(final Channel ch) {
        final ChannelPipeline pipeline = ch.pipeline();

        // 1️⃣ 读超时处理器:如果12小时内没有读取到任何数据,关闭连接,防止资源被闲置连接占用。
        pipeline.addLast(new ReadTimeoutHandler(12, TimeUnit.HOURS));

        // 2️⃣ 写超时处理器:如果12小时内写操作阻塞/失败,关闭连接。
        pipeline.addLast(new WriteTimeoutHandler(12, TimeUnit.HOURS));

        // 3️⃣ HTTP 编解码器:将字节流 ↔️ HTTP 请求/响应对象,是 HTTP 支持的基础。
        pipeline.addLast(new HttpServerCodec());

        // 4️⃣ HTTP 消息聚合器:将多个 HTTP 分段(如多个 HttpContent)聚合成一个完整的 FullHttpRequest。
        //   这是处理 POST 请求/大体积数据传输时的常见做法。
        pipeline.addLast(new HttpObjectAggregator(Integer.MAX_VALUE));

        // 5️⃣ WebSocket 压缩扩展支持:支持 WebSocket 帧的压缩和解压缩。
        //   客户端启用压缩扩展时,可以减少网络流量。
        pipeline.addLast(new WebSocketServerCompressionHandler());

        // 6️⃣ 自定义 WebSocket 处理器:负责 WebSocket 握手、帧处理、心跳、广播等逻辑。
        pipeline.addLast(new WebSocketHandler());

        // 7️⃣ 最终的业务处理器:处理来自 HTTP/WebSocket 的请求消息
        pipeline.addLast(new ServerHandler());
    }
}

参考源码