system column十三Tech
← 返回技术专栏
TECH

Go 设计模式实战:策略模式消除冗余 if-else 的优雅方案

策略模式让你告别臃肿的条件分支,将算法封装为可互换的对象。本文通过 Go 代码演示策略模式的完整实现,分析其在支付路由、日志处理等场景中的实战价值。

Go设计模式

当你的代码里出现一长串 if-elseswitch-case 来处理不同算法分支时,你是否想过有一种更优雅的方式来组织它们?在十三Tech 的代码评审中,策略模式(Strategy Pattern)是我们推荐用来消除这类"条件爆炸"的经典方案。本文将带你从原理到实践,掌握这一行为型设计模式的精髓。

什么是策略模式

策略模式是一种行为型设计模式,它定义一系列算法,将每种算法封装到独立的类中,并使它们可以相互替换。这样,算法的变化不会影响到使用算法的客户端代码。

核心角色

  • 策略接口(Strategy):声明所有具体策略的通用操作方法
  • 具体策略(ConcreteStrategy):实现策略接口,封装具体的算法逻辑
  • 上下文(Context):维护一个策略对象的引用,负责与策略对象交互,将具体执行委托给策略
  • 客户端(Client):创建具体策略并注入到上下文中,也可在运行时动态切换策略

代码实现

下面用 Go 实现一个经典的策略模式示例:根据不同的策略执行不同的业务逻辑。

package main

import "fmt"

// IStrategy 策略接口,声明所有策略必须实现的方法
type IStrategy interface {
	Execute()
}

// strategyA 具体策略 A
type strategyA struct{}

func (a strategyA) Execute() {
	fmt.Println("执行策略 A")
}

// strategyB 具体策略 B
type strategyB struct{}

func (b strategyB) Execute() {
	fmt.Println("执行策略 B")
}

// NewStrategyA 创建策略 A 的实例
func NewStrategyA() IStrategy {
	return &strategyA{}
}

// NewStrategyB 创建策略 B 的实例
func NewStrategyB() IStrategy {
	return &strategyB{}
}

上下文实现

// Context 上下文,负责调用具体的策略
type Context struct {
	strategy IStrategy
}

// SetStrategy 动态设置策略
func (c *Context) SetStrategy(strategy IStrategy) {
	c.strategy = strategy
}

// Execute 执行当前策略
func (c *Context) Execute() {
	c.strategy.Execute()
}

// NewContext 创建上下文实例
func NewContext() *Context {
	return &Context{}
}

客户端调用

func main() {
	// 创建上下文
	context := NewContext()

	// 设置策略 B 并执行
	context.SetStrategy(NewStrategyB())
	context.Execute() // 输出:执行策略 B

	// 运行时动态切换为策略 A
	context.SetStrategy(NewStrategyA())
	context.Execute() // 输出:执行策略 A
}

适用场景

策略模式在以下场景中能够大放异彩:

  • 支付路由系统:根据渠道可用性、费率、优先级动态选择支付通道
  • 日志处理:不同环境(开发、测试、生产)使用不同的日志输出策略
  • 数据压缩:根据数据特征选择 gzip、snappy、zstd 等压缩算法
  • 排序算法:根据数据规模动态选择快速排序、归并排序或插入排序
  • 营销规则引擎:不同类型的促销活动(满减、折扣、返现)对应不同计算策略

优缺点分析

优点

  • 消除条件语句:将复杂的 if-else / switch 替换为策略对象的组合
  • 符合开闭原则:新增算法只需添加新的策略类,无需修改上下文代码
  • 算法可复用:各个策略独立封装,可在不同上下文中复用
  • 运行时动态切换:客户端可以在程序运行期间灵活更换策略

缺点

  • 如果算法极少变化,引入策略模式会增加不必要的复杂度
  • 策略数量过多时,会产生较多的类文件,增加维护成本

总结

策略模式的核心价值在于将"变"与"不变"分离:算法的调用方式是不变的(由上下文统一封装),而具体的算法实现是可变的(由各个策略独立维护)。在十三Tech 的实际项目中,我们在处理多支付方式路由、动态配置切换等场景时大量应用此模式,有效避免了条件分支的无限膨胀,让代码结构更加清晰、易于扩展。

如果你正在为一长串 if-else 感到头疼,策略模式可能就是你要找的解药。