闭包实现策略模式的核心是用函数类型替代接口和类,通过闭包捕获依赖、map 显式注册策略、判断逻辑外提、副作用剥离,兼顾轻量、安全与可测性。
用闭包实现策略模式,核心是把每个分支逻辑封装成独立函数,通过统一签名和外部变量捕获依赖,彻底剥离条件判断与业务执行。它比传统接口+类的方式更轻、更符合 Go 的表达习惯,也避免了运行时注册、nil panic 和类型断言等常见陷阱。
Go 中不需要定义 Strategy 接口或 ConcreteStrategy 类。直接用 func(ctx context.Context, req *Request) (*Response, error) 这样的函数类型作为策略载体。每个策略函数通过闭包“记住”自己所需的依赖,比如数据库句柄、配置项或客户端实例。
alipayHandler := func(ctx context.Context, req *Request) (*Response, error) { return payWithClient(alipayClient, ctx, req) }
wechatHandler := func(ctx context.Context, req *Request) (*Response, error) { return payWithClient(wechatClient, ctx, req) }
把策略函数组织进编译期确定的 map,不靠运行时注册。键为策略标识(如支付方式字符串),值为对应闭包函数。
var strategies = map[string]func(context.Context, *Request) (*Response, error){ "alipay": alipayHandler, "wechat": wechatHandler, "paypal": paypalHandler, }
handler, ok := strategies[req.PaymentMethod]; if !ok { return nil, fmt.Errorf("unknown payment method: %s", req.PaymentMethod) }
每个闭包策略只负责核心计算或 IO,不处理日志、错误包装、重试、metric 上报等副作用。
retryableHandler := retry.Wrap(alipayHandler, 3),而不是让 alipayHandler 自己重试把 if-else 判断本身抽成单独函数,返回策略名。它和策略实现完全隔离,可单独测试、复用或替换为规则引擎。
func selectStrategy(req *Request) string { if req.IsHighRisk() { return "fraud_review" } else if req.Amount > 10000 { return "manual_approve" } else { return req.PaymentMethod } }
name := selectStrategy(req); handler := strategies[name]; ...