命令模式实现疑问:执行失败重试计数与日志记录方案咨询
命令模式下带重试计数的解决方案
核心思路:用装饰器模式扩展命令的重试计数能力,遵循SOLID原则
无需修改原有Command接口和实现,通过包装类添加重试计数功能,既满足开闭原则,又保持单一职责。
- 保持原有Command接口不变
type Command interface { Execute() error }
- 实现重试装饰器类
该类包装原Command实例,负责记录重试次数,并转发执行逻辑:
type RetryCommand struct { cmd Command retryCount int maxRetries int } // 构造函数:传入原命令和最大重试次数 func NewRetryCommand(cmd Command, maxRetries int) *RetryCommand { return &RetryCommand{ cmd: cmd, maxRetries: maxRetries, retryCount: 0, } } // 转发执行逻辑,失败时递增重试计数 func (r *RetryCommand) Execute() error { err := r.cmd.Execute() if err != nil { r.retryCount++ } return err } // 获取当前已重试次数 func (r *RetryCommand) RetryCount() int { return r.retryCount } // 获取允许的最大重试次数 func (r *RetryCommand) MaxRetries() int { return r.maxRetries }
- 修改队列处理逻辑
取出命令后,先检查是否已被包装,未包装则初始化重试装饰器;执行失败后根据计数判断重试或记录日志:
cmd := queue.Take() // 适配未包装的原始命令 retryCmd, isRetryCmd := cmd.(*RetryCommand) if !isRetryCmd { retryCmd = NewRetryCommand(cmd, 2) // 设置最大重试2次 } err := retryCmd.Execute() if err != nil { if retryCmd.RetryCount() <= retryCmd.MaxRetries() { // 未达重试上限,重新入队 queue.Add(retryCmd) } else { // 超过重试次数,记录错误日志 log.Printf("命令执行失败,已耗尽最大重试次数(%d次),错误信息:%v", retryCmd.MaxRetries(), err) } }
SOLID原则契合点
- 开闭原则:原有Command的实现无需修改,通过装饰器扩展重试功能
- 单一职责:原Command专注业务逻辑,RetryCommand仅负责重试计数与执行转发
- 依赖倒置:队列处理逻辑依赖Command抽象,而非具体实现,可灵活替换命令类型
内容的提问来源于stack exchange,提问作者Илья Харламов
相关产品推荐
相关产品推荐

