带优先级的责任链设计模式应用

责任链设计模式

责任链设计模式的典型场景:

  • 一个对象或请求,需要验证一系列的判断,依次执行,顺序不限;核心目的:用于解耦发送方和处理方

带优先级的责任链设计模式:

  • 某些情况下,责任链Handler需要有先后顺序执行

实现

  • ConcreteHandler嵌套BaseHandler,间接实现 BaseHandler的 方法SetNext、HandleNext、Priority

  • 同时ConcreteHandler实现业务Handle方法

  • ByPriority,实现了sort方法的所有方法,实现sort.Sort接口要求

go 复制代码
type Handler interface {
    SetNext(handler Handler)
    Handle(currentValue, PreviousValue float64) (handled bool)
    Priority() int
}

type BaseHandler struct {
    next     Handler
    priority int // 处理器的优先级
}

func (h *BaseHandler) SetNext(handler Handler) {
    h.next = handler
}

func (h *BaseHandler) HandleNext(currentValue, PreviousValue float64) (handled bool) {
    if h.next != nil {
        return h.next.Handle(currentValue, PreviousValue)
    }
    return false
}

func (h *BaseHandler) Priority() int {
    return h.priority
}

type ConcreteHandler struct {
    BaseHandler
    handleFunc func(currentValue, PreviousValue float64) bool // 处理函数
}

func (h *ConcreteHandler) Handle(currentValue, PreviousValue float64) (handled bool) {
    // 如果 handleFunc 处理请求的结果为(返回 true),则停止处理
    if h.handleFunc(currentValue, PreviousValue) {
        return false
    }
    // 否则,传递给下一个处理器
    return h.HandleNext(currentValue, PreviousValue)
}

func NewConcreteHandler(priority int, handleFunc func(currentValue, PreviousValue float64) bool) Handler {
    return &ConcreteHandler{
        BaseHandler: BaseHandler{priority: priority},
        handleFunc:  handleFunc,
    }
}

type ByPriority []Handler

func (a ByPriority) Len() int      { return len(a) }
func (a ByPriority) Swap(i, j int) { a[i], a[j] = a[j], a[i] }

// 1==>优先级最大
func (a ByPriority) Less(i, j int) bool { return a[i].Priority() < a[j].Priority() }

业务逻辑,实现Handler

  • 通过NewConcreteHandler,构建业务Handler,返回业务处理结果;true则不再往下执行
go 复制代码
handlers := []Handler{
        NewConcreteHandler(1, func(_currentValue, _PreviousValue float64) bool {

            pRule := ConstructExpression(PriorityRules)
            expr, _ := govaluate.NewEvaluableExpression(pRule)

            con := make(map[string]interface{})
            con[ExpressionCurrentKey] = _currentValue
            con[ExpressionPreviousValueKey] = _PreviousValue

            result, _ := expr.Evaluate(con)
            if result.(bool) {
                fmt.Printf("当前值%v 前值%v 结果%v 触发表达式:%v\n",
                    con[ExpressionCurrentKey], con[ExpressionPreviousValueKey], result, pRule)
            }

            return result.(bool)

        }),
        NewConcreteHandler(2, func(_currentValue, _PreviousValue float64) bool {

            rule := ConstructExpression(Rules)
            expr, _ := govaluate.NewEvaluableExpression(rule)

            con := make(map[string]interface{})
            con[ExpressionCurrentKey] = _currentValue
            con[ExpressionPreviousValueKey] = _PreviousValue

            result, _ := expr.Evaluate(con)
            if result.(bool) {
                fmt.Printf("当前值%v 前值%v 结果%v 触发表达式:%v\n",
                    con[ExpressionCurrentKey], con[ExpressionPreviousValueKey], result, rule)
            }
            return result.(bool)
        }),
    }

构建链以及调用

  • 根据场景,可以构建多个Handler,并根据优先级执行排序并依次执行SetNext方法,使得对象可以经由多个逻辑依次处理,直至处理结束,实现责任链的执行。
go 复制代码
 sort.Sort(ByPriority(handlers))

    for i := 0; i < len(handlers)-1; i++ {
        handlers[i].SetNext(handlers[i+1])
    }

    for _, handler := range handlers {

        if !handler.Handle(currentValue.Value, *alertRule.PreviousValue) {
            // break
            return true, nil
        }
    }
    return false, nil

效果验证

相关推荐
用户938515635071 分钟前
Docker + Nginx + Node.js:从“我的电脑能跑,你的电脑跑不了”到一键部署
后端·nginx·docker
陆枫Larry2 分钟前
两步验证(2FA )到底是什么?
后端
JavaGuide7 分钟前
我用 Claude Code/ZCode+GLM-5.3 从零做了一款 Agent 游戏!
前端·后端
程序员清风19 分钟前
专业再升级!程序员专属显示器明基RD280UG上手实测!
java·后端·面试
刘立军1 小时前
RESTful 与契约优先:规范接口定义,统一接口设计范式
后端·架构·ai编程
JavaGuide2 小时前
GitHub 4.5 万+ Star!GitNexus 把代码仓库变成了 Claude Code / Codex 能查询的知识图谱
后端·ai编程
子兮曰2 小时前
DeepSeek Harness 架构深潜:一个把 Agent 运行时做成纯插件树的开源 Harness
前端·后端·deepseek
子兮曰3 小时前
AI Agent 完整入门指南:从 LLM 到生产落地的 30+ 个核心概念
前端·后端·agent
渔夫正在掘金3 小时前
Cordis 插件热插拔能力深度解析
后端·node.js
不爱编程的小九九4 小时前
小九源码-springboot004-springboot智能阅读推荐系统
java·spring boot·后端