设计模式之模版方法模式
Table of Contents
介绍 #
模版方法模式在基础对象中提供通用的方法,而模版的使用者只需关心非通用的方法。
举个例子,假设数据同步的过程可分为以下几步:
- 准备数据
- 处理新增的数据
- 处理更新的数据
- 处理删除的数据
对于不同的场景,数据同步的更新逻辑可能都不同,而其他三个步骤(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)
}
总结 #
-
模版模式用于能够抽象出通用部分的代码中。
-
模版模式会导致代码之间的强耦合。比如sort中的排序算法是不变的,如果要修改排序算法,那么所有用到Sort函数的地方都会受到影响。
-
区别于工厂方法模式的由子类决定实例化的类型,模版方法模式由子类决定非通用部分的逻辑。