My App

责任链模式

Chain of Responsibility — 请求沿链条传递,直到某个处理者处理它

一句话理解

把多个处理者连成一条链,请求沿着链依次传递,每个处理者决定自己处理还是传给下一个。

解决什么问题

  • 一个请求可能需要多个对象中的某一个来处理,但发送者不知道该找谁
  • 想避免请求发送者和处理者之间的硬绑定
  • 处理逻辑需要灵活地增减和排序

怎么写

以"请假审批"为例:组长审批 3 天以内,经理审批 7 天以内,总监审批 7 天以上。

public abstract class Approver {
    protected Approver next;  // 下一个处理者

    public Approver setNext(Approver next) {
        this.next = next;
        return next;  // 支持链式调用
    }

    public abstract void approve(int days);
}

public class GroupLeader extends Approver {
    public void approve(int days) {
        if (days <= 3) {
            System.out.println("组长批准了 " + days + " 天假");
        } else if (next != null) {
            next.approve(days);  // 传给下一个
        }
    }
}

public class Manager extends Approver {
    public void approve(int days) {
        if (days <= 7) {
            System.out.println("经理批准了 " + days + " 天假");
        } else if (next != null) {
            next.approve(days);
        }
    }
}

public class Director extends Approver {
    public void approve(int days) {
        System.out.println("总监批准了 " + days + " 天假");
    }
}
// 构建责任链
Approver chain = new GroupLeader();
chain.setNext(new Manager()).setNext(new Director());

chain.approve(2);   // 组长批准了 2 天假
chain.approve(5);   // 经理批准了 5 天假
chain.approve(10);  // 总监批准了 10 天假

前端中的责任链

// Express/Koa 的中间件就是责任链
app.use((req, res, next) => {
  console.log('日志中间件')
  next()  // 传给下一个中间件
})

app.use((req, res, next) => {
  if (!req.headers.token) {
    res.status(401).send('未登录')
    return  // 不调用 next(),链条中断
  }
  next()
})

app.use((req, res) => {
  res.send('业务处理')
})

使用场景

  • Servlet 的 Filter
  • Spring 的 Interceptor
  • Express/Koa 的中间件(middleware)
  • Netty 的 ChannelPipeline
  • 审批流程、权限校验链

On this page