Go语言工厂模式下如何无需重写Do方法实现行为定制
Go语言实现嵌入结构体方法重写的解决方案
问题背景
现有代码通过工厂函数NewPeopleManager创建不同类型的用户实例,Base结构体实现人员通用行为链Do()(依次调用DoPrepare()、DoFirst()、DoSecond())。Working结构体嵌入Base并尝试重写DoFirst()方法,但运行时Base.Do()仍调用自身的DoFirst(),无法触发Working的重写逻辑,且不想为每个用户类型重写复杂的Do()方法。
当前代码运行输出:
Call DoPrepare Base type Call DoFirst Base type Call DoSecond Base type
期望输出:
Call DoPrepare Base type Call DoFirst Working type Call DoSecond Base type
解决方案
Go语言没有传统继承机制,采用组合+接口动态分派实现需求。核心思路是让Base.Do()通过接口调用步骤方法,而非直接调用自身方法,这样嵌入Base的类型重写对应方法后,就能触发动态分派逻辑。
修改后的完整代码
package main import "fmt" type PeopleManager interface { Do() } func NewPeopleManager(typeOfUser string) PeopleManager { switch typeOfUser { case "working": return NewWorking() // 其他用户类型的创建逻辑 default: panic("Not found type") } } // 定义步骤接口,规范所有执行步骤的方法签名 type PeopleSteps interface { DoPrepare() DoFirst() DoSecond() } type Base struct{} // 修改Base.Do(),通过PeopleSteps接口调用步骤方法,实现动态分派 func (b *Base) Do(s PeopleSteps) { s.DoPrepare() s.DoFirst() s.DoSecond() } func (b *Base) DoPrepare() { fmt.Println("Call DoPrepare Base type") } func (b *Base) DoFirst() { fmt.Println("Call DoFirst Base type") } func (b *Base) DoSecond() { fmt.Println("Call DoSecond Base type") } type Working struct { Base } func NewWorking() *Working { return &Working{} } // Working的Do()调用Base.Do()并传入自身,利用接口触发重写方法 func (w *Working) Do() { w.Base.Do(w) } // 重写DoFirst方法,覆盖Base的实现 func (w *Working) DoFirst() { fmt.Println("Call DoFirst Working type") } func main() { m := NewPeopleManager("working") m.Do() }
代码说明
- 定义
PeopleSteps接口:统一所有步骤方法的签名,确保嵌入Base的类型只要实现该接口,就能被Base.Do()调用。 - 修改
Base.Do()参数:通过接口调用步骤方法,替代原有的直接调用自身方法,实现动态分派——调用的是接口实现者的具体方法。 Working的Do()实现:调用Base.Do()并传入自身,Working因嵌入Base自动继承DoPrepare()和DoSecond(),同时重写DoFirst(),完整实现PeopleSteps接口。
运行修改后的代码即可得到期望输出。
内容的提问来源于stack exchange,提问作者Roman Shuplov
相关产品推荐
相关产品推荐

