- 策略模式接口定义
type StrategySorter interface {
sort (arr [] int)
}
- 上下文 Context 定义,实现策略的切换
type SortContext struct {
//接口类型
strategySorter StrategySorter
}
- 上下文构造函数
func (sc *SortContext) SortContext(ss StrategySorter) *SortContext {
sc.strategySorter = ss
return sc
}
- 上下文策略的切换方法
func (sc *SortContext) ExecuteStrategy(arr [] int) {
sc.strategySorter.sort(arr)
}
- 冒泡排序实现策略接口
type BubbleSort struct {
}
func (bs *BubbleSort) sort(arr [] int) {
length := len(arr)
for i := 0; i < length; i++ {
for j := 0; j < length - 1 - i; j++ {
if compare(arr[j],arr[j + 1]) {
swap(arr, j, j + 1)
}
}
}
}
- 快速排序实现策略接口
type QuickSort struct {
}
func (qs *QuickSort) sort(arr [] int) {
quickSort(arr, 0, len(arr) - 1)
}
func quickSort(arr [] int, left, right int) {
if left >= right {
return
}
index := partition(arr, left, right)
quickSort(arr, left, left - 1)
quickSort(arr, index + 1, right)
}
func partition(arr [] int,left, right int) int {
baseNum := arr[left]
for left < right {
for arr[right] >= baseNum && right > left {
right--
}
arr[left] = arr[right]
for arr[left] <= baseNum && right > left {
left++
}
arr[right] = arr[left]
}
arr[right] = baseNum
return right
}
- 测试代码
func main() {
//创建切片
mySlice := make([] int, 10)
InitData(mySlice)
fmt.Println("排 序 前:",mySlice)
context := new(SortContext).SortContext(new(BubbleSort))
context.ExecuteStrategy(mySlice)
fmt.Println("冒泡排序后:",mySlice)
context.SortContext(new(QuickSort))
context.ExecuteStrategy(mySlice)
fmt.Println("快速排序后:",mySlice)
}
- 测试结果
排 序 前: [43 11 59 74 45 77 64 14 4 34]
冒泡排序后: [4 11 14 34 43 45 59 64 74 77]
快速排序后: [4 11 14 34 43 45 59 64 74 77]
总结
如果在一个系统中有许多类,这些类的区别仅在于他们的行为,他们实现的工作和目的是一样的,比如在一个排序的系统中有很多种排序方法,不同排序方法仅算法不同,而他们最终的结果都是得到一个有序序列,那么我们可以通过策略模式选择具体的行为(算法)。比如在上文中,我们只要定义一个 context 对象,就可以通过相同的语句去执行冒泡排序和快速排序的算法,调度语句都是 context.ExecuteStrategy(mySlice)
,不需要通过 if else 或者 switch 语句来判断具体选择什么算法,context 这个对象就负责策略的选择和切换。避免了条件判断,封装了变化。
最后,学习设计模式给我最直观的感觉就是写代码越来越轻松,效率越来越高,当然写代码之前需要花费大量的时间去思考怎么写代码。