如何使用Golang实现模板方法模式_使用Template Method控制执行流程

21次阅读

模板方法模式在go中通过接口定义算法骨架、结构体封装通用流程、函数字段注入具体行为来实现。BaseProcessor统一调度Setup→DoWork→Cleanup,各业务只需组合并设置对应函数即可定制,无需继承,耦合更低。

如何使用Golang实现模板方法模式_使用Template Method控制执行流程

模板方法模式的核心是:定义一个算法的骨架,将某些步骤延迟到子类中实现,让子类在不改变算法结构的前提下重新定义该算法的某些特定步骤。golang 没有继承机制,但可以通过组合 + 接口 + 函数字段优雅地实现这一模式。

用接口定义“算法骨架”

先定义一个接口,声明模板方法(即主流程)和可被定制的钩子方法:

type Processor interface {     // 模板方法:固定执行顺序     Execute()      // 钩子方法:由具体实现决定     Setup() error     DoWork() error     Cleanup() error }

这个接口不强制实现细节,只约定流程节点——Setup → DoWork → Cleanup,而 Execute 是统一调度者。

用结构体封装通用流程逻辑

定义一个基础结构体,内嵌接口字段或直接聚合行为函数,实现可复用的 Execute:

立即学习go语言免费学习笔记(深入)”;

type BaseProcessor struct {     setupFunc   func() error     doWorkFunc  func() error     cleanupFunc func() error }  func (bp *BaseProcessor) Execute() {     if bp.setupFunc != nil {         if err := bp.setupFunc(); err != nil {             log.Printf("setup failed: %v", err)             return         }     }      if bp.doWorkFunc != nil {         if err := bp.doWorkFunc(); err != nil {             log.Printf("work failed: %v", err)             return         }     }      if bp.cleanupFunc != nil {         bp.cleanupFunc() // cleanup 通常不中断流程,即使出错也继续     } }

这样就把“流程控制权”收归 BaseProcessor,各业务只需注入自己的函数即可定制行为。

按需创建具体处理器

无需继承,只需组合 BaseProcessor 并设置对应函数:

  • 文件处理器:打开文件 → 读取内容 → 关闭文件
  • http 请求器:初始化 client → 发起请求 → 关闭连接(如需)
  • 数据库任务:开启事务 → 执行 sql → 提交/回滚

示例:

fileProc := &BaseProcessor{     setupFunc: func() error {         fmt.Println("Opening file...")         return nil     },     doWorkFunc: func() error {         fmt.Println("Processing file data...")         return nil     },     cleanupFunc: func() {         fmt.Println("Closing file...")     }, } fileProc.Execute()

进阶:支持钩子开关与默认行为

可为钩子添加是否启用的标记,或提供默认空实现,增强灵活性:

type ConfigurableProcessor struct {     enableSetup, enableCleanup bool     setupFunc, doWorkFunc, cleanupFunc func() error }  func (cp *ConfigurableProcessor) Execute() {     if cp.enableSetup && cp.setupFunc != nil {         cp.setupFunc()     }     cp.doWorkFunc()     if cp.enableCleanup && cp.cleanupFunc != nil {         cp.cleanupFunc()     } }

也可以把 setupFunc 等设为可选字段,nil 时跳过,避免每次都判空。

基本上就这些。Golang 的模板方法不靠 class 继承,而是靠接口契约 + 函数注入 + 结构体组合来达成同样的目的——流程统一、扩展自由、耦合更低。

text=ZqhQzanResources