模板方法模式(Template Method)
1.意图
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
2.适用性
模板方法应用于下列情况:
- 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
- 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。首先识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。
- 控制子类扩展。模板方法只在特定点调用“hook”操作,这样就只允许在这些点进行扩展。
3.结构
4.代码
package templatemethod
import (
"fmt"
"testing"
)
/*
# 模版方法模式
模版方法模式使用继承机制,把通用步骤和通用方法放到父类中,把具体实现延迟到子类中实现。使得实现符合开闭原则。
如实例代码中通用步骤在父类中实现(`准备`、`下载`、`保存`、`收尾`)下载和保存的具体实现留到子类中,并且提供 `保存`方法的默认实现。
因为Golang不提供继承机制,需要使用匿名组合模拟实现继承。
此处需要注意:因为父类需要调用子类方法,所以子类需要匿名组合父类的同时,父类需要持有子类的引用。
*/
type Cooker interface {
open()
fire()
cooke()
outfire()
close()
}
// 类似于一个抽象类
type CookMenu struct {}
func (CookMenu) open() {
fmt.Println("打开开关")
}
func (CookMenu) fire() {
fmt.Println("开火")
}
// 做菜,交给具体的子类实现
func (CookMenu) cooke() {
}
func (CookMenu) outfire() {
fmt.Println("关火")
}
func (CookMenu) close() {
fmt.Println("关闭开关")
}
// 封装具体步骤
func doCook(cook Cooker) {
cook.open()
cook.fire()
cook.cooke()
cook.outfire()
cook.close()
}
type XiHongShi struct {
CookMenu
}
func (*XiHongShi) cooke() {
fmt.Println("做西红柿")
}
type ChaoJiDan struct {
CookMenu
}
func (ChaoJiDan) cooke() {
fmt.Println("做炒鸡蛋")
}
func TestTemplate(t *testing.T) {
// 做西红柿
xihongshi := &XiHongShi{}
doCook(xihongshi)
// 做炒鸡蛋
chaojidan := &ChaoJiDan{}
doCook(chaojidan)
}