28 条回复  ·  3137 次点击
assiadamo 楼主 小成 2025-8-26 17:13:00
@mightybruce 鸭子类型好像和我这里的需求没啥关系,我关注的是代码复用和重写,interface 在实现特定模式比如策略模式和注入时很有用,struct 嵌套我想他本意也是为了复用基类的代码,但比抽象类残废,基类声明也不能指向组合他的类的实例 var b Base = &Sub{Base: NewBase()} // 编译报错 ,导致要实现像上面说的策略模式还要在上面套一层 interface
assiadamo 楼主 小成 2025-8-26 17:16:29
@mightybruce 他在 main 里面断言,我就问了下为什么不在编译时检测
mightybruce 小成 2025-8-26 17:21:05
我不想说了,我已经强调了 go 不是面向对象语言, 实现策略模式请用函数式和接口混用的方式。
mightybruce 小成 2025-8-26 17:23:21
go 不存在 抽象类,go 也不存在对象( class) 这种, 所以不要再谈什么面向对象。
assiadamo 楼主 小成 2025-8-26 17:29:43
@mightybruce 了解,我这也是写了很多年 Java 思维转不过来,但又需要解决实际问题,只能按这样的写法起模板方便自己。
mightybruce 小成 2025-8-26 17:29:49
给一段策略模式代码 ``` package main import "fmt" // 定义 RouteStrategy 为一个接口,包含 CalculateTime 方法 type RouteStrategy interface { CalculateTime(origin, destination string) int } // 使用函数类型作为策略 type StrategyFunc func(origin, destination string) int // 实现 RouteStrategy 接口的 CalculateTime 方法 func (sf StrategyFunc) CalculateTime(origin, destination string) int { return sf(origin, destination) } // 实现三种策略:步行、骑行、驾车 func WalkStrategyFunc(origin, destination string) int { // 假设固定耗时 30 分钟 return 30 } func BikeStrategyFunc(origin, destination string) int { // 假设固定耗时 15 分钟 return 15 } func DriveStrategyFunc(origin, destination string) int { // 假设固定耗时 10 分钟 return 10 } // 路线规划器 type RoutePlanner struct { strategy RouteStrategy } // 设置策略 func (rp *RoutePlanner) SetStrategy(strategy RouteStrategy) { rp.strategy = strategy } // 估算出行时间 func (rp *RoutePlanner) EstimateTime(origin, destination string) int { return rp.strategy.CalculateTime(origin, destination) } func main() { planner := &RoutePlanner{} // 使用步行策略 walkStrategy := StrategyFunc(WalkStrategyFunc) planner.SetStrategy(walkStrategy) fmt.Println("Walk Time:", planner.EstimateTime("Home", "School")) // 使用骑行策略 bikeStrategy := StrategyFunc(BikeStrategyFunc) planner.SetStrategy(bikeStrategy) fmt.Println("Bike Time:", planner.EstimateTime("Home", "School")) // 使用驾车策略 driveStrategy := StrategyFunc(DriveStrategyFunc) planner.SetStrategy(driveStrategy) fmt.Println("Drive Time:", planner.EstimateTime("Home", "Work")) } ```
monmon 初学 2025-8-26 17:32:49
我没理解错的话,说白了你就是想实现一个 “模板方法模式” https://refactoringguru.cn/design-patterns/template-method/go/example 简单版的代码就是: ```go type Worker interface { MustImplementStep() // 必须被实现的方法 OptionalHook() // 一个有默认行为的、可选的钩子方法 } type BaseWorker struct{} func (b *BaseWorker) OptionalHook() { fmt.Println("-> BaseWorker: 执行默认的钩子逻辑。") } type ConcreteWorker struct { BaseWorker // 嵌入“基类”,OptionalHook 的默认实现。 } // MustImplementStep 实现接口中必须被实现的方法 func (c *ConcreteWorker) MustImplementStep() { fmt.Println("-> ConcreteWorker: 执行必须实现的步骤。") } // 编译期安全检查,如果 ConcreteWorker 未实现 MustImplementStep (注释掉上面方法)会报错 var _ Worker = (*ConcreteWorker)(nil) // OptionalHook “重写”嵌入的钩子方法。 func (c *ConcreteWorker) OptionalHook() { fmt.Println("-> ConcreteWorker: 开始执行重写的钩子逻辑。") // super.method() c.BaseWorker.OptionalHook() fmt.Println("-> ConcreteWorker: 结束执行重写的钩子逻辑。") } func RunTemplate(w Worker) { fmt.Println("--- 模板开始 ---") w.MustImplementStep() w.OptionalHook() fmt.Println("--- 模板结束 ---") } func main() { worker := &ConcreteWorker{} RunTemplate(worker) } ```
unused 初学 2025-8-26 17:44:36
Base 里一部分是默认的方法实现,一部分是组合调用的逻辑,你需要把这两部分拆开。
assiadamo 楼主 小成 2025-8-26 17:44:58
@monmon 了解了,不把 Common 放在 Base 里面而是改成函数像 RunTemplate 注入 Worker ,就会简单很多
123
返回顶部