实现步骤
在Go语言中,可以使用接口和组合来实现模板方法模式。模板方法模式是一种行为设计模式,它定义了一个算法的骨架,将一些步骤的实现延迟到子类中。下面是一个示例代码,演示了如何在Go中实现模板方法模式:
package main
import "fmt"
// AbstractClass 定义抽象类
type AbstractClass interface {
TemplateMethod()
PrimitiveOperation1()
PrimitiveOperation2()
}
// ConcreteClass1 实现具体的子类1
type ConcreteClass1 struct{
}
func (c *ConcreteClass1) TemplateMethod() {
fmt.Println("ConcreteClass1 TemplateMethod")
c.PrimitiveOperation1()
c.PrimitiveOperation2()
}
func (c *ConcreteClass1) PrimitiveOperation1() {
fmt.Println("ConcreteClass1 PrimitiveOperation1")
}
func (c *ConcreteClass1) PrimitiveOperation2() {
fmt.Println("ConcreteClass1 PrimitiveOperation2")
}
// ConcreteClass2 实现具体的子类2
type ConcreteClass2 struct{
}
func (c *ConcreteClass2) TemplateMethod() {
fmt.Println("ConcreteClass2 TemplateMethod")
c.PrimitiveOperation1()
c.PrimitiveOperation2()
}
func (c *ConcreteClass2) PrimitiveOperation1() {
fmt.Println("ConcreteClass2 PrimitiveOperation1")
}
func (c *ConcreteClass2) PrimitiveOperation2() {
fmt.Println("ConcreteClass2 PrimitiveOperation2")
}
func main() {
// 使用具体的子类1
class1 := &ConcreteClass1{
}
class1.TemplateMethod()
fmt.Println()
// 使用具体的子类2
class2 := &ConcreteClass2{
}
class2.TemplateMethod()
}
在上述示例中,AbstractClass
定义了一个抽象类,其中 TemplateMethod
是模板方法,它定义了算法的骨架,调用了两个抽象方法 PrimitiveOperation1
和 PrimitiveOperation2
。ConcreteClass1
和 ConcreteClass2
是具体的子类,它们实现了抽象类的方法。
通过使用接口和组合,我们可以在抽象类中定义模板方法并调用子类的抽象方法,从而实现模板方法模式。在示例中,TemplateMethod
是抽象类中的模板方法,它调用了 PrimitiveOperation1
和 PrimitiveOperation2
方法,具体的子类根据自己的需求来实现这些抽象方法。
运行上述代码将输出以下结果:
ConcreteClass1 TemplateMethod
ConcreteClass1 PrimitiveOperation1
ConcreteClass1 PrimitiveOperation2
ConcreteClass2 TemplateMethod
ConcreteClass2 PrimitiveOperation1
ConcreteClass2 PrimitiveOperation2
可以看到,模板方法 TemplateMethod
在抽象类中定义,并且调用了具体子类实现的抽象方法 PrimitiveOperation1
和 PrimitiveOperation2
。这样,我们就实现了模板方法模式,通过基类调用子类的抽象方法来完成算法的定制化。
实现调用父类的公共方法
以上方法实现了子类调用自己的方法,下面介绍如何类似Java一样调用父类的公共方法
实现步骤
在 Go 语言中,由于语言特性的限制,无法像 Java 中那样直接调用父类的公共方法并间接调用子类实现的抽象方法。Go 语言中没有类继承的概念,只有接口和组合的方式。但是我们可以通过回调函数的方式来实现类似的效果。下面是一个优化后的示例代码:
package main
import "fmt"
// AbstractClass 定义抽象类
type AbstractClass struct {
PrimitiveOperation1 func()
PrimitiveOperation2 func()
}
// TemplateMethod 定义模板方法
func (ac *AbstractClass) TemplateMethod() {
fmt.Println("AbstractClass TemplateMethod")
ac.PrimitiveOperation1()
ac.PrimitiveOperation2()
}
// ConcreteClass1 实现具体的子类1
type ConcreteClass1 struct {
AbstractClass
}
func NewConcreteClass1() *ConcreteClass1 {
cc := &ConcreteClass1{
}
cc.PrimitiveOperation1 = cc.concreteOperation1
cc.PrimitiveOperation2 = cc.concreteOperation2
return cc
}
func (cc *ConcreteClass1) concreteOperation1() {
fmt.Println("ConcreteClass1 concreteOperation1")
}
func (cc *ConcreteClass1) concreteOperation2() {
fmt.Println("ConcreteClass1 concreteOperation2")
}
// ConcreteClass2 实现具体的子类2
type ConcreteClass2 struct {
AbstractClass
}
func NewConcreteClass2() *ConcreteClass2 {
cc := &ConcreteClass2{
}
cc.PrimitiveOperation1 = cc.concreteOperation1
cc.PrimitiveOperation2 = cc.concreteOperation2
return cc
}
func (cc *ConcreteClass2) concreteOperation1() {
fmt.Println("ConcreteClass2 concreteOperation1")
}
func (cc *ConcreteClass2) concreteOperation2() {
fmt.Println("ConcreteClass2 concreteOperation2")
}
func main() {
// 使用具体的子类1
class1 := NewConcreteClass1()
class1.TemplateMethod()
fmt.Println()
// 使用具体的子类2
class2 := NewConcreteClass2()
class2.TemplateMethod()
}
在上述代码中,我们将 AbstractClass
定义为一个结构体,其中的 PrimitiveOperation1
和 PrimitiveOperation2
字段是回调函数,用于指向子类实现的具体方法。在具体的子类中,我们通过创建新的结构体并设置回调函数来实现类似于模板方法模式的效果。
运行上述代码将输出以下结果:
AbstractClass TemplateMethod
ConcreteClass1 concreteOperation1
ConcreteClass1 concreteOperation2
AbstractClass TemplateMethod
ConcreteClass2 concreteOperation1
ConcreteClass2 concreteOperation2
可以看到,通过回调函数的方式,我们实现了类似于模板方法模式的效果。在抽象类的模板方法中调用了子类实现的具体方法。
请注意,这种方式在 Go 语言中是一种常见的模式,可以通过回调函数来实现类似于模板方法模式的行为。虽然不同于 Java 中的继承和抽象方法的调用方式,但在 Go 语言中,通过组合和回调函数可以实现类似的效果。