模板方法模式属于行为型设计模式,核心思想是定义一个操作中的算法骨架,将一些步骤延迟到子类中实现,使得子类可以不改变算法结构的情况下重新定义该算法的某些特定步骤。在Golang中没有传统的类继承机制,我们可以通过接口和结构体组合的方式来实现该模式,完成业务逻辑的流程控制。

模板方法模式核心结构
实现模板方法模式通常需要两个核心部分:
- 抽象模板:定义算法的整体流程,包含模板方法和若干抽象步骤,模板方法按固定顺序调用这些步骤,抽象步骤由具体实现类完成。
- 具体实现:实现抽象模板中定义的抽象步骤,完成具体的业务逻辑。
Golang实现模板方法模式示例
我们以订单处理流程为例,订单处理通常包含校验参数、计算金额、保存订单、发送通知这几个固定步骤,不同订单类型的计算金额和通知方式不同,适合用模板方法模式实现。
定义抽象模板接口
首先定义订单处理器的抽象接口,包含模板方法和抽象步骤:
package main
import "fmt"
// OrderProcessor 订单处理抽象模板接口
type OrderProcessor interface {
// Process 模板方法,定义订单处理的整体流程
Process()
// validate 校验订单参数,抽象步骤
validate()
// calculateAmount 计算订单金额,抽象步骤
calculateAmount()
// saveOrder 保存订单,抽象步骤
saveOrder()
// sendNotification 发送通知,抽象步骤
sendNotification()
}
实现基础模板结构体
定义一个基础结构体实现模板方法,固定流程顺序,抽象步骤由具体结构体实现:
// BaseOrderProcessor 基础订单处理器,实现模板方法
type BaseOrderProcessor struct {
// 嵌入具体实现的结构体,用于调用具体步骤
impl OrderProcessor
}
// Process 模板方法,固定订单处理流程
func (b *BaseOrderProcessor) Process() {
fmt.Println("开始处理订单")
b.impl.validate()
b.impl.calculateAmount()
b.impl.saveOrder()
b.impl.sendNotification()
fmt.Println("订单处理完成")
}
// 基础结构体默认实现抽象步骤,具体实现可以覆盖
func (b *BaseOrderProcessor) validate() {
fmt.Println("默认参数校验")
}
func (b *BaseOrderProcessor) calculateAmount() {
fmt.Println("默认金额计算")
}
func (b *BaseOrderProcessor) saveOrder() {
fmt.Println("默认保存订单")
}
func (b *BaseOrderProcessor) sendNotification() {
fmt.Println("默认发送通知")
}
实现具体订单处理器
以普通订单和会员订单为例,实现不同的金额计算和通知逻辑:
// NormalOrderProcessor 普通订单处理器
type NormalOrderProcessor struct {
BaseOrderProcessor
}
// 初始化普通订单处理器
func NewNormalOrderProcessor() *NormalOrderProcessor {
processor := &NormalOrderProcessor{}
processor.BaseOrderProcessor.impl = processor
return processor
}
// calculateAmount 普通订单金额计算逻辑
func (n *NormalOrderProcessor) calculateAmount() {
fmt.Println("普通订单:按商品原价计算金额,无折扣")
}
// sendNotification 普通订单通知逻辑
func (n *NormalOrderProcessor) sendNotification() {
fmt.Println("普通订单:发送短信通知用户")
}
// VipOrderProcessor 会员订单处理器
type VipOrderProcessor struct {
BaseOrderProcessor
}
// 初始化会员订单处理器
func NewVipOrderProcessor() *VipOrderProcessor {
processor := &VipOrderProcessor{}
processor.BaseOrderProcessor.impl = processor
return processor
}
// calculateAmount 会员订单金额计算逻辑
func (v *VipOrderProcessor) calculateAmount() {
fmt.Println("会员订单:商品原价打9折计算金额")
}
// sendNotification 会员订单通知逻辑
func (v *VipOrderProcessor) sendNotification() {
fmt.Println("会员订单:发送短信和邮件通知用户")
}
调用示例
在main函数中调用不同的订单处理器,查看流程执行效果:
func main() {
fmt.Println("=== 处理普通订单 ===")
normalProcessor := NewNormalOrderProcessor()
normalProcessor.Process()
fmt.Println("n=== 处理会员订单 ===")
vipProcessor := NewVipOrderProcessor()
vipProcessor.Process()
}
运行上述代码,输出结果如下:
=== 处理普通订单 === 开始处理订单 默认参数校验 普通订单:按商品原价计算金额,无折扣 默认保存订单 普通订单:发送短信通知用户 订单处理完成 === 处理会员订单 === 开始处理订单 默认参数校验 会员订单:商品原价打9折计算金额 默认保存订单 会员订单:发送短信和邮件通知用户 订单处理完成
模式优势与注意事项
使用Golang实现模板方法模式的优势在于:
- 固定了业务流程的顺序,避免不同实现中流程错乱的问题。
- 公共逻辑放在基础结构体中,减少重复代码,提升可维护性。
- 新增订单类型时只需要实现差异化的步骤,符合开闭原则。
需要注意的点:
- 抽象步骤的命名要清晰,明确每个步骤的职责,避免后续实现混乱。
- 如果流程步骤可能频繁变化,不适合使用该模式,否则修改模板会影响所有实现类。
- Golang中没有继承,通过结构体嵌入和接口组合实现时,要注意
impl字段的赋值,确保调用的是具体实现的步骤。