一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

如何利用闭包实现的策略模式重构复杂的 if-else 分支逻辑

时间:2026-06-07 10:32:52 编辑:袖梨 来源:一聚教程网

闭包实现策略模式的核心是用函数类型替代接口和类,通过闭包捕获依赖、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 + 显式兜底

把策略函数组织进编译期确定的 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) }
  • 这样既保类型安全,又防 panic,还方便单元测试覆盖所有 key

边界清晰:策略只做一件事

每个闭包策略只负责核心计算或 IO,不处理日志、错误包装、重试、metric 上报等副作用。

  • 日志统一由上层 Context 或中间件打;错误由调用方统一 wrap;重试逻辑放在策略外的 wrapper 函数中
  • 比如: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]; ...
  • 后续加风控策略、灰度开关、AB 实验,都只需改这个函数,不动策略 map 和具体 handler

热门栏目