概述
- 意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
- 主要解决:一些方法通用,却在每一个子类都重新写了这一方法。
- 何时使用:有一些通用的方法。
- 如何解决:将这些通用算法抽象出来。
- 关键代码:通用逻辑在抽象类实现,其他步骤在子类实现。
- 注意事项:由于 Golang 语言本身的限制,模板模式实现时对可见性的控制不太好;如果提供接口的基类实现,需要将所有步骤都抽象成接口,不然会有问题。
UML
实现
package main
import (
"fmt"
)
// Cooking 炒菜,也可以为其提供基类
type Cooking interface {
AddIngredient() //加主料
AddSeasoning() //加调料
}
//该方法内定义了一些通用的步骤
func Template(c Cooking) {
//注意,该模式在于对步骤的限制上,只暴露部分步骤
// step1
fmt.Println("添加食用大豆油")
// step2.添加主料
c.AddIngredient()
//step3
fmt.Println("添加食用盐")
//step4.添加辅料
c.AddSeasoning()
}
// 炒土豆丝
type CookingPotato struct {
}
func (c *CookingPotato) AddIngredient() {
fmt.Println("添加土豆丝")
}
func (c *CookingPotato) AddSeasoning() {
fmt.Println("添加十三香")
}
// 炒肉
type CookingMeat struct {
}
func (c *CookingMeat) AddIngredient() {
fmt.Println("添加猪肉片")
}
func (c *CookingMeat) AddSeasoning() {
fmt.Println("添加料酒")
}
//客户端
func main() {
//
potato := &CookingPotato{}
Template(potato)
fmt.Println("\n")
meat := &CookingMeat{}
Template(meat)
}
UML 代码
@startuml
abstract Cooking {
-AddOil()
+AddIngredient()
-AddSalt()
+AddSeasoning()
+Cook()
}
class CookingPotato{
+AddIngredient()
+AddSeasoning()
}
class CookingMeat{
+AddIngredient()
+AddSeasoning()
}
Cooking <|-- CookingPotato
Cooking <|-- CookingMeat
@enduml