【设计模式】参数校验逻辑复杂,代码长?用责任链

责任链模式属于行为设计模式

GoF定义:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

场景

1.在接收web请求时,需要进行参数验证。

2.在消费消息时,需要对消费到消息进行参数验证。

上述场景中,若参数验证比较复杂,责任链可以依次判断,后续若减少或者增加参数校验,会变得很容易。

责任链中的一个方法只专注判断一个参数,体现了单一职责的设计原则。

示例

支付单报关: 跨境电商,订单状态未付款变成已付款状态时,需要进行支付单报关

技术实现:

1.订阅订单的状态变化的消息

2.验证订单的参数

3.支付报关

实现的流程非常简单,不用责任链也可以实现。

1.需要校验的参数非常多

2.参数校验的逻辑非常复杂

3.参数的校验顺序经常改变

4.后续会增加需要校验的参数

5.后续会删除校验的参数

在以上的场景中,使用责任链可以让代码变得容易维护和扩展。

实现

基础处理

go 复制代码
// 处理器接口  
type Handler interface {  
    SetNext(handler Handler) Handler  
    Handle(request *RequestParam, response *ResponseResult)  
}  
  
// 基础处理器  
type BaseHandler struct {  
    next Handler  
}  
  
func (h *BaseHandler) SetNext(handler Handler) Handler {  
    h.next = handler  
    return handler  
}  
  
func (h *BaseHandler) Handle(request *RequestParam, response *ResponseResult) {  
    if h.next != nil {  
       h.next.Handle(request, response)  
    }  
}

BaseHandler 实现基础处理。需要校验的字段可以基于这个进行扩展。
next来标识下一步的操作,使用过gi内框架开发程序的朋友一定马上联想到了中间件。

责任链的运用非常广泛,在各种工作流软件及中间件组件中都会遇到。

字段处理器

订单号验证处理器

go 复制代码
// 订单号验证处理器
type OrderNoHandler struct {
	BaseHandler
}

func NewOrderNoHandler() *OrderNoHandler {
	return &OrderNoHandler{}
}

func (h *OrderNoHandler) Handle(request *RequestParam, response *ResponseResult) {
	if request.OrderNo == "" {
		response.Success = false
		response.Message = "订单号不能为空"
		return
	}
	fmt.Println("订单号证通过")
	h.BaseHandler.Handle(request, response)
}

支付人验证处理器

go 复制代码
type PaymentNameHandler struct {  
    BaseHandler  
}  
  
func NewPaymentNameHandler() *PaymentNameHandler {  
    return &PaymentNameHandler{}  
}  
  
func (h *PaymentNameHandler) Handle(request *RequestParam, response *ResponseResult) {  
    if request.PaymentName == "" {  
       response.Success = false  
       response.Message = "支付宝人不能为空"  
       return  
    }  
    fmt.Println("支付人验证通过")  
    h.BaseHandler.Handle(request, response)  
}

支付人身份证验证器

go 复制代码
// 支付人身份证验证处理器  
type PaymentIdCardHandler struct {  
    BaseHandler  
}  
  
func NewPaymentIdCardHandler() *PaymentIdCardHandler {  
    return &PaymentIdCardHandler{}  
}  
  
func (h *PaymentIdCardHandler) Handle(request *RequestParam, response *ResponseResult) {  
    if request.PaymentIdCard == "" {  
       response.Success = false  
       response.Message = "支付人身份证不能为空"  
       return  
    }  
    fmt.Println("支付人身份证验证通过")  
    h.BaseHandler.Handle(request, response)  
}

支付流水号验证器

go 复制代码
// 支付流水号验证处理器  
type TradeNoHandler struct {  
    BaseHandler  
}  
  
func NewTradeNoHandler() *TradeNoHandler {  
    return &TradeNoHandler{}  
}  
  
func (h *TradeNoHandler) Handle(request *RequestParam, response *ResponseResult) {  
    if request.TradeNo == "" {  
       response.Success = false  
       response.Message = "支付流水号不能为空"  
       return  
    }  
    fmt.Println("支付流水号验证通过")  
    h.BaseHandler.Handle(request, response)  
}

如何使用

go 复制代码
// 支付报关处理器  
type DeclareHandler struct {  
    BaseHandler  
}  
  
func NewDeclareHandler() *DeclareHandler {  
    return &DeclareHandler{}  
}  
  
func (h *DeclareHandler) Handle(request *RequestParam, response *ResponseResult) {  
    // 支付报关  
    response.Success = true  
    response.Message = "支付单报关成功"  
}
go 复制代码
// 创建责任链  
orderNoHandler := NewOrderNoHandler()  
  
// 组装责任链  
orderNoHandler.SetNext(NewPaymentNameHandler()).  
    SetNext(NewPaymentIdCardHandler()).  
    SetNext(NewTradeNoHandler()).  
    SetNext(NewDeclareHandler())

完整示例

go 复制代码
package main  
  
import "fmt" 
  
// 请求和响应结构  
type RequestParam struct {  
    OrderNo       string  
    PaymentName   string  
    PaymentIdCard string  
    TradeNo       string  
}  
  
type ResponseResult struct {  
    Success bool  
    Message string  
}  
  
// 处理器接口  
type Handler interface {  
    SetNext(handler Handler) Handler  
    Handle(request *RequestParam, response *ResponseResult)  
}  
  
// 基础处理器  
type BaseHandler struct {  
    next Handler  
}  
  
func (h *BaseHandler) SetNext(handler Handler) Handler {  
    h.next = handler  
    return handler  
}  
  
func (h *BaseHandler) Handle(request *RequestParam, response *ResponseResult) {  
    if h.next != nil {  
       h.next.Handle(request, response)  
    }  
}  
  
// 订单号验证处理器  
type OrderNoHandler struct {  
    BaseHandler  
}  
  
func NewOrderNoHandler() *OrderNoHandler {  
    return &OrderNoHandler{}  
}  
  
func (h *OrderNoHandler) Handle(request *RequestParam, response *ResponseResult) {  
    if request.OrderNo == "" {  
       response.Success = false  
       response.Message = "订单号不能为空"  
       return  
    }  
    fmt.Println("订单号证通过")  
    h.BaseHandler.Handle(request, response)  
}  
  
// 支付人验证处理器  
type PaymentNameHandler struct {  
    BaseHandler  
}  
  
func NewPaymentNameHandler() *PaymentNameHandler {  
    return &PaymentNameHandler{}  
}  
  
func (h *PaymentNameHandler) Handle(request *RequestParam, response *ResponseResult) {  
    if request.PaymentName == "" {  
       response.Success = false  
       response.Message = "支付宝人不能为空"  
       return  
    }  
    fmt.Println("支付人验证通过")  
    h.BaseHandler.Handle(request, response)  
}  
  
// 支付人身份证验证处理器  
type PaymentIdCardHandler struct {  
    BaseHandler  
}  
  
func NewPaymentIdCardHandler() *PaymentIdCardHandler {  
    return &PaymentIdCardHandler{}  
}  
  
func (h *PaymentIdCardHandler) Handle(request *RequestParam, response *ResponseResult) {  
    if request.PaymentIdCard == "" {  
       response.Success = false  
       response.Message = "支付人身份证不能为空"  
       return  
    }  
    fmt.Println("支付人身份证验证通过")  
    h.BaseHandler.Handle(request, response)  
}  
  
// 支付流水号验证处理器  
type TradeNoHandler struct {  
    BaseHandler  
}  
  
func NewTradeNoHandler() *TradeNoHandler {  
    return &TradeNoHandler{}  
}  
  
func (h *TradeNoHandler) Handle(request *RequestParam, response *ResponseResult) {  
    if request.TradeNo == "" {  
       response.Success = false  
       response.Message = "支付流水号不能为空"  
       return  
    }  
    fmt.Println("支付流水号验证通过")  
    h.BaseHandler.Handle(request, response)  
}  
  
// 支付报关处理器  
type DeclareHandler struct {  
    BaseHandler  
}  
  
func NewDeclareHandler() *DeclareHandler {  
    return &DeclareHandler{}  
}  
  
func (h *DeclareHandler) Handle(request *RequestParam, response *ResponseResult) {  
    // 支付报关  
    response.Success = true  
    response.Message = "支付单报关成功"  
}  
  
func main() {  
    // 创建责任链  
    orderNoHandler := NewOrderNoHandler()  
  
    // 组装责任链  
    orderNoHandler.SetNext(NewPaymentNameHandler()).  
       SetNext(NewPaymentIdCardHandler()).  
       SetNext(NewTradeNoHandler()).  
       SetNext(NewDeclareHandler())  
  
    // 创建请求  
    request := &RequestParam{  
       PaymentName:   "张三丰",  
       PaymentIdCard: "989987200110100093",  
       TradeNo:       "TR20250101080000",  
       OrderNo:       "OR20250101080000",  
    }  
  
    // 处理请求  
    response := &ResponseResult{}  
    orderNoHandler.Handle(request, response)  
  
    // 输出结果  
    fmt.Println("结果:", response.Message)  
}

总结

责任链模式优点:

1.动态分配职责 :灵活处理请求

2.增强扩展性 :支持新增处理者而无需修改现有代码

3.职责明确 :代码清晰易维护

4.灵活处理请求 :支持多步骤、多条件的请求处理

5.减少代码重复 :避免冗余逻辑

6.支持优先级处理:根据需求调整链的顺序

怎样?那么多的好处,还不在你的项目中运用起来。

相关推荐
小马爱打代码4 分钟前
设计模式:迪米特法则 - 最少依赖,实现高内聚低耦合
设计模式·迪米特法则
骊山道童25 分钟前
设计模式-观察者模式
观察者模式·设计模式
终身学习基地1 小时前
第二篇:go包管理
开发语言·后端·golang
图南随笔2 小时前
Spring Boot(二十一):RedisTemplate的String和Hash类型操作
java·spring boot·redis·后端·缓存
吃饭了呀呀呀2 小时前
🐳 《Android》 安卓开发教程 - 三级地区联动
android·java·后端
shengjk12 小时前
SparkSQL Join的源码分析
后端
Linux编程用C2 小时前
Rust编程学习(一): 变量与数据类型
开发语言·后端·rust
uhakadotcom2 小时前
一文读懂DSP(需求方平台):程序化广告投放的核心基础与实战案例
后端·面试·github
吴生43963 小时前
数据库ALGORITHM = INSTANT 特性研究过程
后端