Go 中可通过接口 + 组合 + 函数字段模拟模板方法模式:定义含 Validate/Process/Notify/LogResult 方法的 PaymentProcessor 接口,Executor 结构体持该接口并实现固定流程 Execute(),具体类型如 CreditCardProcessor 实现接口方法以定制步骤逻辑。

在 Go 语言中,由于没有类继承和抽象方法的原生支持,无法像 Java 或 C++ 那样直接实现传统意义上的模板方法模式(Template Method Pattern),但可以通过 接口 + 组合 + 函数字段 的方式优雅地模拟该模式:定义算法骨架(主流程),将可变步骤延迟到具体类型或函数中实现。
用接口定义“算法契约”
先定义一个接口,描述模板方法要调用的关键步骤。这些方法代表子类需“定制”的细节逻辑:
type PaymentProcessor interface {Validate() error Process() error Notify() error LogResult(success bool) }
这个接口不包含主流程(如 Execute()),仅声明钩子步骤——相当于抽象基类中的抽象方法。
定义模板方法(算法骨架)
创建一个通用执行器结构体,内嵌接口,并提供不可重写的主流程方法:
立即学习 “go 语言免费学习笔记(深入)”;
type Executor struct {processor PaymentProcessor} func (e *Executor) Execute() error { if err := e.processor.Validate(); err != nil {e.processor.LogResult(false) return err } if err := e.processor.Process(); err != nil { e.processor.LogResult(false) return err } if err := e.processor.Notify(); err != nil { e.processor.LogResult(false) return err } e.processor.LogResult(true) return nil }
这就是“模板方法”:流程固定(校验 → 处理 → 通知 → 日志),每步调用接口方法,具体行为由传入的 PaymentProcessor 实现决定。
子类式实现:结构体 + 接口实现
让具体类型(如 CreditCardProcessor)实现接口,填充细节逻辑:
type CreditCardProcessor struct {CardNumber string Amount float64} func (c *CreditCardProcessor) Validate() error { if len(c.CardNumber) < 12 {return fmt.Errorf("invalid card number") } return nil } func (c *CreditCardProcessor) Process() error { fmt.Printf("Charging $%.2f to card %s……n", c.Amount, c.CardNumber[:4]) return nil // 模拟成功 } func (c *CreditCardProcessor) Notify() error { fmt.Println("Sending email receipt……") return nil } func (c *CreditCardProcessor) LogResult(success bool) {status := "success" if !success { status = "failed"} fmt.Printf("[Log] Credit card payment %sn", status) }
使用时只需组合:
proc := &CreditCardProcessor{CardNumber: "4532015112830366", Amount: 99.99,} executor := &Executor{processor: proc} executor.Execute() // 按模板流程运行
更灵活方案:用函数字段替代接口
若逻辑简单、不想定义完整接口,可用结构体内嵌函数字段,直接注入行为:
type FlexibleExecutor struct {ValidateFunc func() error ProcessFunc func() error NotifyFunc func() error LogFunc func(success bool) } func (e *FlexibleExecutor) Execute() error { if err := e.ValidateFunc(); err != nil {e.LogFunc(false) return err } if err := e.ProcessFunc(); err != nil { e.LogFunc(false) return err } if err := e.NotifyFunc(); err != nil { e.LogFunc(false) return err } e.LogFunc(true) return nil } // 使用示例 exec := &FlexibleExecutor{ValidateFunc: func() error {return nil}, ProcessFunc: func() error { fmt.Println("Processing via API……"); return nil }, NotifyFunc: func() error { fmt.Println("Slack notification sent"); return nil }, LogFunc: func(s bool) {fmt.Printf("Result: %tn", s) }, } exec.Execute()
这种方式适合快速原型、测试桩或高度动态的流程定制。
Go 中的模板方法本质是“控制反转”:主流程掌控执行顺序,细节由使用者通过接口实现或函数注入。关键不在语法是否像 OOP,而在是否清晰分离了稳定骨架与易变逻辑——这正是模板方法模式的核心价值。