模板方法模式属于行为型设计模式,其核心是在一个方法中定义算法的骨架,将某些步骤的具体实现延迟到子类或具体实现体中。Golang没有class和继承,但可以通过结构体嵌入和接口组合来模拟这一模式,从而把固定的流程逻辑集中管理,把易变的逻辑交给调用方实现。

模板方法模式的基本结构
在Golang中,我们通常定义一个接口来描述可变步骤,再定义一个基础结构体保存流程模板,基础结构体持有接口类型的字段,流程方法按顺序调用接口方法。
定义步骤接口
先抽象出流程中会发生变化的环节:
package main
// 定义可变步骤的接口
type OrderProcessor interface {
Validate() error
Process() error
Save() error
}
// 模板结构体,封装固定流程
type BaseOrder struct {
impl OrderProcessor
}
// 模板方法:固定的执行顺序
func (b *BaseOrder) Execute() error {
if err := b.impl.Validate(); err != nil {
return err
}
if err := b.impl.Process(); err != nil {
return err
}
if err := b.impl.Save(); err != nil {
return err
}
return nil
}
实现具体业务
不同的订单类型只需要实现OrderProcessor接口,然后嵌入BaseOrder并调用Execute即可复用流程。
package main
import "fmt"
// 普通订单实现
type NormalOrder struct {
BaseOrder
}
func (n *NormalOrder) Validate() error {
fmt.Println("校验普通订单")
return nil
}
func (n *NormalOrder) Process() error {
fmt.Println("处理普通订单")
return nil
}
func (n *NormalOrder) Save() error {
fmt.Println("保存普通订单")
return nil
}
func NewNormalOrder() *NormalOrder {
o := &NormalOrder{}
// 将自身赋值给基类中的接口字段
o.BaseOrder.impl = o
return o
}
在main函数中调用
通过统一入口执行,流程逻辑完全不需要在业务代码里重写。
package main
func main() {
order := NewNormalOrder()
if err := order.Execute(); err != nil {
fmt.Println("执行失败:", err)
}
}
使用场景与注意事项
当多个模块具有一致的步骤顺序,但每步实现不同时,非常适合用该模式。需要注意以下几点:
- 接口粒度要合理,避免步骤拆得太碎
- 模板方法里不要写具体业务,只做流程编排
- 若步骤需要动态跳过,可在接口中增加开关方法
小结
Golang借助接口与结构体嵌入,可以很自然地实现模板方法模式。把不变的流程收口,把变化的点抽象成接口,能显著降低重复代码,提高可维护性。在实际项目中,例如支付流水、任务调度等都能看到它的身影。