策略模式
约 569 字大约 2 分钟
2025-12-27
定义
定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。
策略模式的优点
- 算法可以自由切换
- 避免使用多重条件判断
- 扩展性良好
策略模式的缺点
- 策略类数量增多
- 所有策略类都需要对外暴露
策略模式的使用场景
- 多个类只有在算法或行为上稍有不同的场景
- 算法需要自由切换的场景
- 需要屏蔽算法规则的场景
策略模式的注意事项
如果系统中的一个策略家族的具体策略数量超过4个,则需要考虑使用混合模式,解决策略类膨胀和对外暴露的问题,否则日后的系统维护就会成为一个烫手山芋,谁都不想接。
示例
自定义 slice(使用不同排序策略)
// sort/sort.go 策略接口
type Interface interface {
Len() int
Less(i, j int) bool
Swap(i, j int)
}
// sort/sort.go 上下文(Context),执行排序流程
// 依赖策略接口提供的具体步骤,运行时可以注入不同策略
func Sort(data Interface) {
n := data.Len()
if n <= 1 {
return
}
limit := bits.Len(uint(n))
pdqsort(data, 0, n, limit)
}
// 自定义策略示例
type User struct {
Name string
Age int
}
// 策略 1:按年龄排序
type ByAge []User
func (a ByAge) Len() int { return len(a) }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
// 策略 2:按名字排序
type ByName []User
func (a ByName) Len() int { return len(a) }
func (a ByName) Less(i, j int) bool { return a[i].Name < a[j].Name }
func (a ByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
// 运行时切换策略
func main() {
users := []User{
{"AAA", 30},
{"BBB", 20},
{"CCC", 10},
}
sort.Sort(ByAge(users)) // 使用“按年龄”策略
fmt.Println(users)
sort.Sort(ByName(users)) // 使用“按名字”策略
fmt.Println(users)
}函数式策略
// sort/slice.go
func Slice(x any, less func(i, j int) bool) {
rv := reflectlite.ValueOf(x)
swap := reflectlite.Swapper(x)
length := rv.Len()
limit := bits.Len(uint(length))
pdqsort_func(lessSwap{less, swap}, 0, length, limit)
}
// 传入排序策略函数(Function Strategy)
// less 函数定义了两个元素的比较规则,决定排序行为
sort.Slice(users, func(i, j int) bool {
return users[i].Age < users[j].Age
})