使用Golang实现策略模式(Strategy)_动态切换业务算法逻辑

2次阅读

go中用接口定义策略需先抽象可变行为并统一输入输出,如paymentstrategy接口仅含pay方法;运行时通过字段赋值切换策略,避免mapswitch实现;初始化时须传入依赖并校验非空。

使用Golang实现策略模式(Strategy)_动态切换业务算法逻辑

Go 里怎么用接口定义策略?

策略模式在 Go 里不靠抽象类或继承,而是靠 Interface 契约。你得先想清楚:哪些行为会变?这些行为的输入输出是否一致?比如支付策略,Pay(amount float64) Error 就是公共契约。

  • 接口方法必须精简,只保留真正需要动态替换的部分;加多了反而让实现类负担重
  • 不要为“将来可能扩展”提前加方法,等出现具体新策略再改接口(Go 崇尚小接口)
  • 接口名建议用形容词或名词,比如 PaymentStrategy,别叫 IPaymentStrategy(Go 不用 I 前缀)
type PaymentStrategy interface {     Pay(amount float64) error }

如何在运行时切换策略?

不是靠 new 一策略实例再 if-else,而是把策略当参数传、当字段存、当返回值用。核心是:策略对象本身可被赋值、替换、缓存

  • 把策略作为结构体字段声明,初始化时注入,后续直接调用 strategy.Pay()
  • 切换时直接赋新值:order.Strategy = &AlipayStrategy{},不需要反射或工厂函数
  • 如果策略依赖外部配置(如 API key),确保它在创建时就完成初始化,别拖到 Pay 里才检查
type Order Struct {     Strategy PaymentStrategy } <p>func (o *Order) Process(amount float64) error { return o.Strategy.Pay(amount) // 调用当前策略 }

为什么不用 map[String]func 或 switch 实现策略?

map[string]func 或大段 switch 看似简单,但很快会失控:

  • 新增策略要改两处:注册 map 和写 func 实现,违反开闭原则
  • 每个 func 都得自己处理错误、日志、重试逻辑,无法复用
  • 无法携带状态(比如支付宝策略需要 appID 字段,纯函数做不到)
  • 单元测试困难:没法 mock 一个匿名函数,但可以 mock 接口

所以宁可多写一个结构体,也别用函数表硬凑策略模式。

立即学习go语言免费学习笔记(深入)”;

策略初始化时容易漏掉什么?

策略不是裸 struct,它往往需要依赖项。常见疏忽:

  • 忘记传入必要依赖,导致 Pay 运行时报 nil pointer dereference
  • 把依赖设成全局变量,造成并发不安全(比如多个 goroutine 共享同一个 http client)
  • 在策略方法里做 heavy 初始化(如读配置文件),导致首次调用慢且不可控

正确做法:所有依赖通过构造函数传入,并在初始化时验证非空。

type WechatPayStrategy struct {     client *http.Client     appID  string } <p>func NewWechatPayStrategy(client <em>http.Client, appID string) </em>WechatPayStrategy { if client == nil { panic("client is required") } return &WechatPayStrategy{client: client, appID: appID} }

策略不是写完就扔的工具,它的生命周期和业务上下文绑定越紧,越容易出错。特别是并发场景下,别让策略实例跨请求共享状态。

text=ZqhQzanResources