行为型 策略模式

为什么需要策略模式

策略模式是定义一箩筐算法(行为),将每个算法独立封装,并且允许相互替换。策略模式是在定义、创建、使用这三部分可以灵活使用(解耦)。策略在定义的时候一般采用接口并且具体的策略实现同一个接口。

还有一个使用场景就是当代码的if else 分支判断太多的时候,我们确实可以考虑策略模式来简化代码。当然必须if else的pattern有一致性才能做到的,实际上就是采用了查表方式来做简化而已。

实现

实现一般需要实现一个factory。我这里用了极客时间的那位老师的例子,不过我采用的golang的写法。我这里还采取了一个办法来去除if else。这里的例子是根据输入文件大小动态的选择排序算法。

go.mod

module strategy

go 1.13

strategy.go

package strategy

import "fmt"

var sortAlgFactory map[string]ISortAlg

func init() {
	sortAlgFactory = make(map[string]ISortAlg)
	sortAlgFactory["QuickSort"] = QuickSort{}
	sortAlgFactory["ExternalSort"] = ExternalSort{}
}

type Sorter struct {
	algs []AlgRange
}

const GB uint64 = 1000 * 1000 * 1000

func NewSorter() Sorter {
	sorter := Sorter{}
	sorter.algs = append(sorter.algs, AlgRange{
		start: 0,
		end:   6 * GB,
		alg:   sortAlgFactory["QuickSort"],
	})
	sorter.algs = append(sorter.algs, AlgRange{
		start: 6 * GB,
		end:   100 * GB,
		alg:   sortAlgFactory["ExternalSort"],
	})
	return sorter
}

func (sorter Sorter) SortFile(filePath string, size uint64) {
	var sortAlg ISortAlg

	// Get rid of if else here
	for _, alg := range sorter.algs {
		if alg.inRange(size) {
			sortAlg = alg.getAlg()
			break
		}
	}

	if sortAlg == nil {
		fmt.Println("No available sorting algorithm")
		return
	}

	sortAlg.sort(filePath)
}

type ISortAlg interface {
	sort(filePath string)
}

type QuickSort struct{}

func (sort QuickSort) sort(filePath string) {
	fmt.Println(filePath + " is sorted by QuickSort")
}

type ExternalSort struct{}

func (sort ExternalSort) sort(filePath string) {
	fmt.Println(filePath + " is sorted by ExternalSort")
}

type AlgRange struct {
	start uint64
	end   uint64
	alg   ISortAlg
}

func (algRange AlgRange) inRange(size uint64) bool {
	return size >= algRange.start && size <= algRange.end
}

func (algRange AlgRange) getAlg() ISortAlg {
	return algRange.alg
}

strategy_test.go

package strategy_test

import (
	"strategy"
)

func ExampleSorter() {
	exampleSorter := strategy.NewSorter()
	exampleSorter.SortFile("abc.txt", 5*strategy.GB)
	exampleSorter.SortFile("def.txt", 10*strategy.GB)
	exampleSorter.SortFile("def.txt", 101*strategy.GB)
	// output:
	// abc.txt is sorted by QuickSort
	// def.txt is sorted by ExternalSort
	// No available sorting algorithm
}

执行: go test strategy -v

Previous
Next