跳到主要内容

策略模式

问题

Go 中如何实现策略模式?和传统 OOP 有什么区别?

答案

函数类型实现(Go 惯用)

Go 的一等函数使策略模式极其简洁:

// 策略就是函数类型
type SortStrategy func([]int) []int

// 直接传入函数作为策略
func ProcessData(data []int, strategy SortStrategy) []int {
return strategy(data)
}

// 使用
result := ProcessData(data, sort.Ints) // 内置排序
result := ProcessData(data, bubbleSort) // 自定义排序
result := ProcessData(data, func(d []int) []int { // 匿名函数
slices.Reverse(d)
return d
})

接口实现

需要状态或复杂策略时用接口:

// 压缩策略接口
type Compressor interface {
Compress(data []byte) ([]byte, error)
Extension() string
}

type GzipCompressor struct{ level int }
type ZstdCompressor struct{}

func (g *GzipCompressor) Compress(data []byte) ([]byte, error) { /* ... */ }
func (g *GzipCompressor) Extension() string { return ".gz" }

func (z *ZstdCompressor) Compress(data []byte) ([]byte, error) { /* ... */ }
func (z *ZstdCompressor) Extension() string { return ".zst" }

// 使用
type FileProcessor struct {
compressor Compressor
}

func (fp *FileProcessor) Process(data []byte) error {
compressed, err := fp.compressor.Compress(data)
// ...
}

http.Handler 就是策略模式

标准库中 http.Handler 接口天然就是策略模式:

// 不同的 Handler 就是不同的处理策略
mux.Handle("/api", apiHandler)
mux.Handle("/static", fileHandler)

常见面试问题

Q1: 什么时候用函数,什么时候用接口?

答案

  • 函数类型:策略简单、无状态、只有一个方法 → func(...) ...
  • 接口:策略有多个方法、需要持有状态、需要 Mock 测试 → interface

经验法则:先用函数,复杂了再提取接口。

Q2: Go 标准库中有哪些策略模式?

答案

  • sort.Interface:自定义排序策略
  • http.Handler:请求处理策略
  • io.Writer:写入目标策略(文件/网络/Buffer)
  • hash.Hash:哈希算法策略

相关链接