最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如何利用闭包实现的策略模式重构复杂的 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
相关文章
- 异环噩梦缠身怎么快速过 06-10
- SWE Infrabench Evaluating 安全吗?权限、隐私和风险检查 06-10
- 《挖掘者米娜》全8只猫位置和演奏方法分享 06-10
- 任性足球什么时候出 公测上线时间预告 06-10
- 植物大战僵尸2卡在花界面无法进入游戏解决方法 06-10
- dnf手游深渊派对邀请函怎样获得 dnf手游深渊派对邀请函获取方式汇总 06-10