19. 职责链模式(Chain of Responsibility)
19. 职责链模式(Chain of Responsibility)
问题:请求需要经过多个处理者,但不想让发送者知道谁会处理。
核心:处理者串成链,每个处理者决定自己处理还是传给下一个。
type RequestContext = {
token?: string;
role?: string;
user?: string;
};
class Handler {
#next?: Handler;
setNext(h: Handler): Handler { this.#next = h; return h; }
handle(request: RequestContext): string | null {
if (this.#next) return this.#next.handle(request);
return null;
}
}
class AuthHandler extends Handler {
handle(request: RequestContext): string | null {
if (!request.token) return '未认证';
return super.handle(request);
}
}
class RoleHandler extends Handler {
handle(request: RequestContext): string | null {
if (request.role !== 'admin') return '权限不足';
return super.handle(request);
}
}
class LogHandler extends Handler {
handle(request: RequestContext): string | null {
console.log(`管理员 ${request.user} 操作已记录`);
return super.handle(request);
}
}
const auth = new AuthHandler();
auth.setNext(new RoleHandler()).setNext(new LogHandler());
const result = auth.handle({ token: 'abc', role: 'admin', user: '小明' });
// 管理员 小明 操作已记录
console.log(result); // null(全部通过)package chain
import "fmt"
type Handler interface {
SetNext(Handler) Handler
Handle(request map[string]any) string
}
type BaseHandler struct{ next Handler }
func (h *BaseHandler) SetNext(next Handler) Handler {
h.next = next
return next
}
func (h *BaseHandler) Handle(request map[string]any) string {
if h.next != nil {
return h.next.Handle(request)
}
return ""
}
type AuthHandler struct{ BaseHandler }
func (h *AuthHandler) Handle(req map[string]any) string {
if _, ok := req["token"]; !ok {
return "未认证"
}
return h.BaseHandler.Handle(req)
}
type RoleHandler struct{ BaseHandler }
func (h *RoleHandler) Handle(req map[string]any) string {
if role, _ := req["role"].(string); role != "admin" {
return "权限不足"
}
return h.BaseHandler.Handle(req)
}
type LogHandler struct{ BaseHandler }
func (h *LogHandler) Handle(req map[string]any) string {
user, _ := req["user"].(string)
fmt.Printf("管理员 %s 操作已记录\n", user)
return h.BaseHandler.Handle(req)
}实战场景
- Web 中间件:请求依次经过日志、鉴权、限流、参数校验、业务处理、错误处理。
- 表单校验链:必填、格式、长度、业务唯一性、权限检查按顺序执行,失败就提前返回。
- 客服工单升级:机器人、普通客服、高级客服、专家团队逐级处理,当前层处理不了就传给下一层。
- 日志处理:debug、info、warn、error 由不同 handler 判断是否处理或继续传递。
- 权限判断:先检查登录,再检查角色,再检查资源归属,再检查特殊策略。
- 支付风控:设备风险、账号风险、金额风险、黑名单、人工审核一层层判断。
- 编译器处理:词法分析、语法分析、类型检查、优化、代码生成形成处理链。
- 数据清洗:去空值、格式化、标准化、去重、补默认值按步骤传递数据。
- API 网关:跨域、鉴权、路由、熔断、负载均衡、响应改写都可以作为链上节点。
- 插件流水线:构建工具的 loader、transform、hook 往往就是一条可扩展处理链。
Express/Koa 的中间件机制就是这个模式。