信息发布→ 登录 注册 退出

如何使用Golang实现策略模式_Golang策略模式业务逻辑封装方法

发布时间:2026-01-04

点击量:
Go语言策略模式推荐三种实现:1. 简单无状态用函数类型;2. 带状态依赖用接口+结构体;3. 可扩展查找用map注册表,需注意错误统一、context透传与并发安全。

Go 语言没有类继承和接口实现的强制约束,策略模式不能照搬 Java/C# 那套写法;它更适合用函数类型、接口+结构体组合、或 map[string]func 的轻量方式来封装业务逻辑。

func 类型定义策略最简洁

当策略逻辑简单、无状态、不需复用内部字段时,直接用函数类型是最自然的选择。比如支付方式:微信支付、支付宝、银行卡,各自只需一个 Pay(amount float64) error 行为。

定义统一策略类型:

type PayStrategy func(amount float64) error

实现不同策略:

var WechatPay PayStrategy = func(amount float64) error {
    fmt.Println("WeChat pay:", amount)
    return nil
}

var Alipay PayStrategy = func(amount float64) error { fmt.Println("Alipay:", amount) return nil }

使用时直接传入函数值,无需实例化结构体:

func DoPayment(strategy PayStrategy, amount float64) error {
    return strategy(amount)
}

DoPayment(WechatPay, 99.9)

⚠️ 注意:这种写法无法在策略内部访问上下文(如用户 ID、订单号),也不便于加日志/监控中间件——需要升级为接口方式。

用接口 + 结构体实现带状态的策略

当策略需要持有配置、依赖外部服务(如调用某个 *http.Client 或数据库连接),就该用接口定义行为,结构体承载状态。

定义接口:

type PaymentProcessor interface {
    Process(orderID string, amount float64) error
}

实现微信支付策略:

type WechatProcessor struct {
    client *http.Client
    appID  string
}

func (w *WechatProcessor) Process(orderID string, amount float64) error { // 使用 w.client 和 w.appID 发起请求 fmt.Printf("WeChat processing %s for %.2f\n", orderID, amount) return nil }

工厂函数按需返回具体策略:

func NewPaymentProcessor(kind string, cfg Config) PaymentProcessor {
    switch kind {
    case "wechat":
        return &WechatProcessor{client: &http.Client{}, appID: cfg.AppID}
    case "alipay":
        return &AlipayProcessor{gateway: cfg.AlipayURL}
    default:
        panic("unknown processor")
    }
}

✅ 这种方式支持依赖注入、单元测试 mock、运行时动态切换,是中大型业务推荐的写法。

map[string]PaymentProcessor 实现策略注册与查找

避免每次 if-else 或 switch 判断类型,把策略实例缓存起来,按 key 查找更清晰、可扩展性更强。

初始化全局策略注册表:

var processors = make(map[string]PaymentProcessor)

func RegisterProcessor(name string, p PaymentProcessor) { processors[name] = p }

func GetProcessor(name string) (PaymentProcessor, bool) { p, ok := processors[name] return p, ok }

注册时:

RegisterProcessor("wechat", &WechatProcessor{...})
RegisterProcessor("alipay", &AlipayProcessor{...})

使用时:

if p, ok := GetProcessor("wechat"); ok {
    p.Process("ORD-123", 199.0)
}

⚠️ 注意:注册时机必须早于首次使用(通常放在 init() 或应用启动时);并发读写需加 sync.RWMutex(如果运行时会动态增删策略)。

策略切换时容易忽略的两个点

一是错误处理一致性:不同策略可能返回不同格式的错误(如网络超时 vs 参数校验失败),建议统一封装成自定义错误类型,带 Code() 方法便于上层分类响应。

二是上下文传递:别把 context.Context 硬编码进接口方法签名里——应该让所有策略方法都接收 ctx context.Context,否则超时控制、trace 透传都会断掉。

例如接口应定义为:

type PaymentProcessor interface {
    Process(ctx context.Context, orderID string, amount float64) error
}

不是所有策略都需要用到 ctx,但留着它,比后面补加更安全。

标签:# java  # go  # golang  # go语言  # 支付宝  # 微信  # 编码  # app  # 微信支付  # switch  # 注册表  # c#  # gate  
在线客服
服务热线

服务热线

4008888355

微信咨询
二维码
返回顶部
×二维码

截屏,微信识别二维码

打开微信

微信号已复制,请打开微信添加咨询详情!