责任链模式
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 - 审批流程、权限校验链