Skip to main content
  1. internet/

设计模式之模版方法模式

·581 words·2 mins·
Table of Contents

介绍 #

模版方法模式在基础对象中提供通用的方法,而模版的使用者只需关心非通用的方法。

举个例子,假设数据同步的过程可分为以下几步:

  1. 准备数据
  2. 处理新增的数据
  3. 处理更新的数据
  4. 处理删除的数据

对于不同的场景,数据同步的更新逻辑可能都不同,而其他三个步骤(1、2、4)则不会改变。因此,我们可以制作一个通用的模版,这样,使用方在使用时只需处理更新逻辑即可。

type Sync interface{
  Update()
}

func SyncData(sync Sync) {
  prepare()
  add()
  sync.Update()
  delete()
}

type Syncer struct{}

func (s syncer) Update() {}

func sync() {
  SyncData(new(Syncer))
}

官方库中的实例 #

go中的排序方法就应用了这一模式。

src/sort/sort.go中,定义了用户自定义行为的接口:

type Interface interface {
	Len() int
	Less(i, j int) bool
	Swap(i, j int)
}

并且提供了模版方法:

func Sort(data Interface) {
	n := data.Len()
	if n <= 1 {
		return
	}
	limit := bits.Len(uint(n))
	pdqsort(data, 0, n, limit)
}

Interface中的三个方法会在pdqsort中使用,具体算法代码较复杂,可自行阅读源码。

有了这个模版,我们就可以对任意数据进行排序,前提是这些数据能够实现Len()、Less()、Swap(), example:

type MineSorter struct {
	scores []int
}

func (m MineSorter) Len() int {
	return len(m.scores)
}

func (m MineSorter) Less(i, j int) bool {
	return m.scores[i] < m.scores[j]
}

func (m MineSorter) Swap(i, j int) {
	m.scores[i], m.scores[j] = m.scores[j], m.scores[i]
}

func Example() {
	sorter := MineSorter{scores: []int{4,2,2,5,3,9,0,1}}
	sort.Sort(sorter)
}

总结 #

  1. 模版模式用于能够抽象出通用部分的代码中。

  2. 模版模式会导致代码之间的强耦合。比如sort中的排序算法是不变的,如果要修改排序算法,那么所有用到Sort函数的地方都会受到影响。

  3. 区别于工厂方法模式的由子类决定实例化的类型,模版方法模式由子类决定非通用部分的逻辑。