模板模式
模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。这里的“算法”,我们可以理解为广义上的“业务逻辑”,并不特指数据结构和算法中的“算法”。这里的算法骨架就是“模板”,包含算法骨架的方法就是“模板方法”,这也是模板方法模式名字的由来。
模板模式有两大作用:复用和扩展。其中复用指的是,所有的子类可以复用父类中提供的模板方法的代码。扩展指的是,框架通过模板模式提供功能扩展点,让框架用户可以在不修改框架源码的情况下,基于扩展点定制化框架的功能。
// 模板模式:模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。
// 模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。
package template
import "fmt"
type ITemplate interface {
method1()
method2()
}
type TemplateExecutor struct {
template ITemplate
}
func NewTemplateExecutor(template ITemplate) *TemplateExecutor {
return &TemplateExecutor{template: template}
}
// 模板方法
// 模板模式把一个算法中不变的流程抽象到父类的模板方法 templateMethod() 中
// 将可变的部分 method1()、method2() 留给子类 ContreteClass1 和 ContreteClass2 来实现。所有的子类都可以复用父类中模板方法定义的流程代码
func (t TemplateExecutor) templateMethod() {
// ...
t.template.method1()
// ...
t.template.method2()
// ...
}
// 父类
type Template struct{}
func (t Template) method1() {
fmt.Println("Template: method1")
}
func (t Template) method2() {
fmt.Println("Template: method2")
}
// ConcreteClass1 实现类,实现 ITemplate
type ConcreteClass1 struct {
Template
}
func NewConcreteClass1() *ConcreteClass1 {
return &ConcreteClass1{}
}
func (cc ConcreteClass1) method1() {
// ...
fmt.Println("ConcreteClass1: method1")
}
func (cc ConcreteClass1) method2() {
// ...
fmt.Println("ConcreteClass1: method2")
}
// ConcreteClass2 实现类,实现 ITemplate
type ConcreteClass2 struct {
Template
}
func NewConcreteClass2() *ConcreteClass2 {
return &ConcreteClass2{}
}
// 只重新实现了 method1
func (cc ConcreteClass2) method1() {
// ...
fmt.Println("ConcreteClass2: method1")
}
//func (cc ConcreteClass2) method2() {
// // ...
// fmt.Println("ConcreteClass2: method2")
//}
package template
import (
"fmt"
"testing"
)
func TestAppDemo(t *testing.T) {
demo1 := NewConcreteClass1()
NewTemplateExecutor(demo1).templateMethod()
fmt.Println("--------------------")
demo2 := NewConcreteClass2()
NewTemplateExecutor(demo2).templateMethod()
}