15 模版方法模式 -- go语言设计模式
模板方法模式定义了一个算法的步骤,并允许子类别为一个或多个步骤提供其实践方式。让子类别在不改变算法架构的情况下,重新定义算法中的某些步骤
模版方法模式的实现代码
package main
import "fmt"
//抽象类,制作饮料,包裹一个模板的全部实现步骤
type Beverage interface {
BoilWater() //煮开水
Brew() //冲泡
PourInCup() //倒入杯中
AddThings() //添加酌料
WantAddThings() bool //是否加入酌料Hook
}
//封装一套流程模板,让具体的制作流程继承且实现
type template struct {
b Beverage
}
//封装的固定模板
func (t *template) MakeBeverage() {
if t == nil {
return
}
t.b.BoilWater()
t.b.Brew()
t.b.PourInCup()
//子类可以重写该方法来决定是否执行下面动作
if t.b.WantAddThings() == true {
t.b.AddThings()
}
}
//具体的模板子类 制作咖啡
type MakeCaffee struct {
template //继承模板
}
func NewMakeCaffee() *MakeCaffee {
makeCaffe := new(MakeCaffee)
//b 为Beverage,是MakeCaffee的接口,这里需要给接口赋值,指向具体的子类对象
//来触发b全部接口方法的多态特性。
makeCaffe.b = makeCaffe
return makeCaffe
}
func (mc *MakeCaffee) BoilWater() {
fmt.Println("将水煮到100摄氏度")
}
func (mc *MakeCaffee) Brew() {
fmt.Println("用水冲咖啡豆")
}
func (mc *MakeCaffee) PourInCup() {
fmt.Println("将充好的咖啡倒入陶瓷杯中")
}
func (mc *MakeCaffee) AddThings() {
fmt.Println("添加牛奶和糖")
}
func (mc *MakeCaffee) WantAddThings() bool {
return true //启动Hook条件
}
//具体的模板子类 制作茶
type MakeTea struct {
template //继承模板
}
func NewMakeTea() *MakeTea {
makeTea := new(MakeTea)
//b 为Beverage,是MakeTea,这里需要给接口赋值,指向具体的子类对象
//来触发b全部接口方法的多态特性。
makeTea.b = makeTea
return makeTea
}
func (mt *MakeTea) BoilWater() {
fmt.Println("将水煮到80摄氏度")
}
func (mt *MakeTea) Brew() {
fmt.Println("用水冲茶叶")
}
func (mt *MakeTea) PourInCup() {
fmt.Println("将充好的咖啡倒入茶壶中")
}
func (mt *MakeTea) AddThings() {
fmt.Println("添加柠檬")
}
func (mt *MakeTea) WantAddThings() bool {
return false //关闭Hook条件
}
func main() {
//1. 制作一杯咖啡
makeCoffee := NewMakeCaffee()
makeCoffee.MakeBeverage() //调用固定模板方法
fmt.Println("------------")
//2. 制作茶
makeTea := NewMakeTea()
makeTea.MakeBeverage()
}
终端输出
模版方法模式的代码拆分
1.项目的准备工作
找到 go 的 GOPATH
$ go env //可以查看 GOPATH
在 GOPATH 目录下创建3个文件夹
1.bin文件夹 -- 存放编译后的二进制文件
2.pkg文件夹 -- 存放编译后的库文件
3.src文件夹 -- 存放源码文件
2.创建文件夹
// -- 在项目文件夹 template_mode 里创建新文件夹
// template -- 存放装饰者的全部文件
3.接口文件 -- template文件夹
文件1 -- beverage.go
package template
//抽象类,制作饮料,包裹一个模板的全部实现步骤
type Beverage interface {
BoilWater() //煮开水
Brew() //冲泡
PourInCup() //倒入杯中
AddThings() //添加酌料
WantAddThings() bool //是否加入酌料Hook
}
4.结构体文件 -- template文件夹
文件1 -- template.go
package template
//封装一套流程模板,让具体的制作流程继承且实现
type template struct {
b Beverage
}
//封装的固定模板
func (t *template) MakeBeverage() {
if t == nil {
return
}
t.b.BoilWater()
t.b.Brew()
t.b.PourInCup()
//子类可以重写该方法来决定是否执行下面动作
if t.b.WantAddThings() == true {
t.b.AddThings()
}
}
文件2 -- makecaffee.go
package template
import "fmt"
//具体的模板子类 制作咖啡
type MakeCaffee struct {
template //继承模板
}
func NewMakeCaffee() *MakeCaffee {
makeCaffe := new(MakeCaffee)
//b 为Beverage,是MakeCaffee的接口,这里需要给接口赋值,指向具体的子类对象
//来触发b全部接口方法的多态特性。
makeCaffe.b = makeCaffe
return makeCaffe
}
func (mc *MakeCaffee) BoilWater() {
fmt.Println("将水煮到100摄氏度")
}
func (mc *MakeCaffee) Brew() {
fmt.Println("用水冲咖啡豆")
}
func (mc *MakeCaffee) PourInCup() {
fmt.Println("将充好的咖啡倒入陶瓷杯中")
}
func (mc *MakeCaffee) AddThings() {
fmt.Println("添加牛奶和糖")
}
func (mc *MakeCaffee) WantAddThings() bool {
return true //启动Hook条件
}
文件3 -- maketea.go
package template
import "fmt"
//具体的模板子类 制作茶
type MakeTea struct {
template //继承模板
}
func NewMakeTea() *MakeTea {
makeTea := new(MakeTea)
//b 为Beverage,是MakeTea,这里需要给接口赋值,指向具体的子类对象
//来触发b全部接口方法的多态特性。
makeTea.b = makeTea
return makeTea
}
func (mt *MakeTea) BoilWater() {
fmt.Println("将水煮到80摄氏度")
}
func (mt *MakeTea) Brew() {
fmt.Println("用水冲茶叶")
}
func (mt *MakeTea) PourInCup() {
fmt.Println("将充好的咖啡倒入茶壶中")
}
func (mt *MakeTea) AddThings() {
fmt.Println("添加柠檬")
}
func (mt *MakeTea) WantAddThings() bool {
return false //关闭Hook条件
}
5.主文件 -- main.go 在项目文件夹
package main
import (
"design/template_mode/template"
"fmt"
)
func main() {
//1. 制作一杯咖啡
makeCoffee := template.NewMakeCaffee()
makeCoffee.MakeBeverage() //调用固定模板方法
fmt.Println("------------")
//2. 制作茶
makeTea := template.NewMakeTea()
makeTea.MakeBeverage()
}