system column十三Tech
← 返回技术专栏
TECH

Go 设计模式实战:责任链模式构建灵活的请求处理流水线

责任链模式让请求沿着处理链逐层传递,实现请求发送者与接收者的解耦。本文详解 Go 实现方案,覆盖中间件、审批流、过滤器等经典应用场景。

Go设计模式

当你的系统需要依次执行多个处理步骤,且这些步骤的组合和顺序可能在运行时动态变化时,如何设计才能既保持灵活又避免代码耦合?在十三Tech 的后端架构中,责任链模式(Chain of Responsibility Pattern)是处理这类"流水线式"需求的利器。本文将深入讲解其原理,并给出可直接落地的 Go 实现。

什么是责任链模式

责任链模式是一种行为型设计模式,它允许将请求沿着一条处理链进行传递,直到链上的某个处理者能够处理该请求为止。这种模式将请求的发送者和接收者解耦,多个处理者对象都有机会处理请求。

核心角色

  • 处理者接口(Handler):声明处理请求的通用接口,通常包含 HandleSetNext 方法
  • 基础处理者(BaseHandler):可选的抽象层,封装处理者共用的样板代码(如维护下一个处理者的引用)
  • 具体处理者(ConcreteHandler):包含处理请求的实际逻辑,决定是否处理请求以及是否继续向后传递
  • 客户端(Client):负责组装处理链,并将请求发送给链上的任意处理者

代码实现

下面用 Go 实现一个责任链模式的经典示例:多级审批流程。

package main

import "fmt"

// Handler 处理者接口
type Handler interface {
	SetNext(handler Handler)
	Handle(requestID int) // 处理请求
}

// BaseHandler 基础处理者,封装 next 引用
type BaseHandler struct {
	name      string
	next      Handler
	threshold int // 当前处理者能处理的最大请求级别
}

// SetNext 设置下一个处理者
func (bh *BaseHandler) SetNext(handler Handler) {
	bh.next = handler
}

// Handle 基础处理逻辑:能处理则处理,不能则传递
func (bh *BaseHandler) Handle(requestID int) {
	if requestID <= bh.threshold {
		fmt.Printf("[%s] 已处理请求 %d\n", bh.name, requestID)
		return
	}
	if bh.next != nil {
		fmt.Printf("[%s] 无法处理请求 %d,转发给下一级...\n", bh.name, requestID)
		bh.next.Handle(requestID)
	} else {
		fmt.Printf("[%s] 请求 %d 无人可处理\n", bh.name, requestID)
	}
}

// NewHandler 创建处理者
func NewHandler(name string, threshold int) *BaseHandler {
	return &BaseHandler{name: name, threshold: threshold}
}

客户端组装与调用

func main() {
	// 组装责任链:组长 -> 经理 -> 总监
	leader := NewHandler("组长", 1)
	manager := NewHandler("经理", 3)
	director := NewHandler("总监", 5)

	leader.SetNext(manager)
	manager.SetNext(director)

	// 发送请求
	leader.Handle(2) // 经理处理
	leader.Handle(5) // 总监处理
	leader.Handle(6) // 无人处理
}

适用场景

责任链模式在以下场景中极具实用价值:

  • 中间件流水线:HTTP 请求依次经过日志、鉴权、限流、参数校验等中间件
  • 审批工作流:请假、报销等业务单据按级别逐级审批
  • 过滤器链:对数据进行多级过滤和转换
  • 事件总线:事件依次经过多个监听器处理,直到被消费
  • 敏感词过滤:文本经过多级检测规则(关键词、正则、AI 模型)

优缺点分析

优点

  • 请求与处理解耦:发送者无需知道具体由哪个处理者执行
  • 符合单一职责:每个处理者只负责自己的逻辑
  • 符合开闭原则:新增处理者只需插入链中,不影响已有代码
  • 动态组合:链的结构可以在运行时组装或调整

缺点

  • 部分请求可能未被处理(链末端无兜底逻辑时)
  • 链过长时可能影响性能,且不易调试
  • 循环引用风险:如果链组装不当可能导致无限循环

总结

责任链模式的精髓在于**"各司其职,能者居之"**。它将复杂的处理流程拆解为独立的处理节点,每个节点只关心自己的职责范围,超出范围则优雅地传递给下一个节点。在十三Tech 的网关层设计中,我们用责任链模式串联了认证、鉴权、限流、日志等多个中间件,让每一层都保持单一职责,同时整体流程又具备极强的可扩展性。

当你下一次面对"多级处理、逐级传递"的需求时,责任链模式会是一个值得优先考虑的设计方案。