美文网首页
责任链模式

责任链模式

作者: Xiao_Yang | 来源:发表于2023-09-23 11:17 被阅读0次

    责任链模式是一种行为型设计模式,它将一个请求以链式的方式传递给一系列的处理对象,每个处理对象都有机会处理该请求或将其传递给下一个对象。这种模式可以避免请求的发送者和接收者之间的直接耦合,并使多个对象都有机会处理请求,直到其中一个对象能够处理为止。

    以下是一个使用Go语言实现的责任链模式的简单示例:

    package main
    
    import "fmt"
    
    // 请求结构体
    type Request struct {
        amount int
    }
    
    // 处理器接口
    type Handler interface {
        SetNext(handler Handler)
        Handle(request Request)
    }
    
    // 具体处理器A
    type ConcreteHandlerA struct {
        next Handler
    }
    
    func (h *ConcreteHandlerA) SetNext(handler Handler) {
        h.next = handler
    }
    
    func (h *ConcreteHandlerA) Handle(request Request) {
        if request.amount <= 100 {
            fmt.Println("ConcreteHandlerA 处理了请求:", request.amount)
        } else if h.next != nil {
            h.next.Handle(request)
        } else {
            fmt.Println("没有处理器可以处理该请求")
        }
    }
    
    // 具体处理器B
    type ConcreteHandlerB struct {
        next Handler
    }
    
    func (h *ConcreteHandlerB) SetNext(handler Handler) {
        h.next = handler
    }
    
    func (h *ConcreteHandlerB) Handle(request Request) {
        if request.amount > 100 && request.amount <= 500 {
            fmt.Println("ConcreteHandlerB 处理了请求:", request.amount)
        } else if h.next != nil {
            h.next.Handle(request)
        } else {
            fmt.Println("没有处理器可以处理该请求")
        }
    }
    
    // 具体处理器C
    type ConcreteHandlerC struct {
        next Handler
    }
    
    func (h *ConcreteHandlerC) SetNext(handler Handler) {
        h.next = handler
    }
    
    func (h *ConcreteHandlerC) Handle(request Request) {
        if request.amount > 500 {
            fmt.Println("ConcreteHandlerC 处理了请求:", request.amount)
        } else if h.next != nil {
            h.next.Handle(request)
        } else {
            fmt.Println("没有处理器可以处理该请求")
        }
    }
    
    func main() {
        // 创建具体处理器
        handlerA := &ConcreteHandlerA{}
        handlerB := &ConcreteHandlerB{}
        handlerC := &ConcreteHandlerC{}
    
        // 设置处理器的下一个处理对象
        handlerA.SetNext(handlerB)
        handlerB.SetNext(handlerC)
    
        // 创建请求
        request1 := Request{amount: 50}
        request2 := Request{amount: 200}
        request3 := Request{amount: 1000}
    
        // 发送请求
        handlerA.Handle(request1)
        handlerA.Handle(request2)
        handlerA.Handle(request3)
    }
    

    在上述示例代码中,创建了三个具体处理器(ConcreteHandlerA、ConcreteHandlerB和ConcreteHandlerC),它们分别处理请求的不同金额范围。每个处理器都有一个指向下一个处理器的引用,形成一个处理器链。当请求发送到责任链上时,会按照链的顺序进行处理。如果当前处理器可以处理该请求,则处理请求;否则,将请求传递给下一个处理器,直到有处理器能够处理为止。执行示例代码后,你将看到不同金额的请求由相应的处理器进行处理。

    web框架Echo代码解析实例

    基于责任链模式的思想,Golang Web框架Echo的源代码中的处理器逻辑可以被解析为一个请求的处理链。在Echo框架中,HTTP请求经过一系列的处理器(中间件)进行处理,直到到达最终的路由处理函数。

    以下是大致的处理流程:

    1. 创建Echo实例,定义路由规则。
    2. 注册中间件:你可以添加多个中间件来处理请求。这些中间件按照注册的顺序形成一个处理器链。
    3. 接收HTTP请求:当收到一个HTTP请求时,Echo会将请求传递给第一个中间件进行处理。
    4. 中间件处理:每个中间件都有一个处理函数,用于处理请求。它可以在请求到达路由处理函数之前执行一些通用的逻辑,如身份验证、日志记录、错误处理等。
    5. 请求传递:中间件可以选择将请求传递给下一个中间件进行处理。这可以通过调用next(c echo.Context)来实现,其中c是当前的上下文对象。
    6. 路由处理函数:如果没有更多的中间件需要处理请求,请求将达到最终的路由处理函数。这个处理函数将实际处理请求的业务逻辑。

    在Echo框架源代码中,你将找到类似于以下结构的处理器链:

    type MiddlewareFunc func(echo.HandlerFunc) echo.HandlerFunc
    
    type Echo struct {
        // ...
        middleware []MiddlewareFunc
        // ...
    }
    
    func (e *Echo) Use(middleware ...MiddlewareFunc) {
        e.middleware = append(e.middleware, middleware...)
    }
    
    func (e *Echo) ServeHTTP(w http.ResponseWriter, req *http.Request) {
        // ...
        c := e.newContext(w, req)
        h := func(c echo.Context) error {
            return e.router.Handle(c)
        }
    
        // 迭代,执行中间件链
        for i := len(e.middleware) - 1; i >= 0; i-- {
            h = e.middleware[i](h)
        }
    
        if err := h(c); err != nil {
            e.HTTPErrorHandler(err, c)
        }
    
        c.response.writer.WriteHeader(c.response.status)
    }
    

    在上面的示例代码中,Echo的中间件通过Use方法进行注册,并按照注册顺序存储在middleware切片中。

    ServeHTTP方法中,请求通过一个迭代循环,按照逆序依次经过每个中间件的处理,并形成处理函数h。最终,请求被传递给路由处理函数e.router.Handle(c)进行实际的业务处理。

    通过使用这种处理器链的方式,Echo可以在请求处理过程中提供统一的逻辑处理和灵活的扩展机制,使得开发者可以方便地添加和管理不同的中间件,实现各种功能,如身份验证、日志记录、缓存等。

    web框架Gin代码解析实例

    Golang Web框架Gin的源代码中的处理器逻辑也可以基于责任链模式进行解析。

    在Gin框架中,HTTP请求通过一系列的中间件和路由组进行处理,直到达到最终的处理函数。

    以下是大致的处理流程:

    1. 创建Gin实例,定义路由规则。
    2. 注册中间件:可以添加多个中间件来处理请求。这些中间件形成一个处理器链。
    3. 接收HTTP请求:当收到一个HTTP请求时,Gin会将请求传递给第一个中间件进行处理。
    4. 中间件处理:每个中间件都有一个处理函数,用于处理请求。它可以在请求到达路由处理函数之前执行一些通用的逻辑,如身份验证、日志记录、错误处理等。
    5. 请求传递:中间件可以选择将请求传递给下一个中间件进行处理。这可以通过调用c.Next()来实现,其中c是当前的上下文对象。
    6. 路由处理函数:如果没有更多的中间件需要处理请求,请求将到达最终的路由处理函数。这个处理函数将实际处理请求的业务逻辑。

    在Gin框架的源代码中,你将找到类似以下结构的处理器链:

    type HandlerFunc func(*Context)
    
    type Engine struct {
        // ...
        router     *Router
        middleware []HandlerFunc
        // ...
    }
    
    func (engine *Engine) Use(middleware ...HandlerFunc) {
        engine.middleware = append(engine.middleware, middleware...)
    }
    
    func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
        c := engine.createContext(w, req)
        // 中间件处理
        engine.handleHTTPRequest(c)
    }
    
    func (engine *Engine) handleHTTPRequest(c *Context) {
        lastHandler := engine.router.handleHTTPRequest
        for i := len(engine.middleware) - 1; i >= 0; i-- {
            lastHandler = engine.middleware[i](lastHandler)
        }
        lastHandler(c)
    }
    

    在上述示例代码中,Gin的中间件通过Use方法进行注册,并按照注册顺序存储在middleware切片中。在ServeHTTP方法中,创建了一个上下文对象c,然后通过handleHTTPRequest方法对请求进行处理。

    handleHTTPRequest方法中,请求依次经过每个中间件的处理,形成一个处理函数链。这个处理函数链起始于路由组件的handleHTTPRequest方法,并逆序遍历每个中间件,将前一个处理函数作为参数传递给下一个中间件的执行函数。最终,请求将传递给最后一个中间件作为回调函数lastHandler,完成请求的处理。

    通过使用这种责任链模式的方式,Gin框架能够实现请求处理过程的统一逻辑和可扩展性。中间件可以处理诸如身份验证、请求记录、错误处理等通用逻辑,而路由处理函数可以专注于实际的业务逻辑。这种设计模式使得开发者能够方便地添加、移除和管理中间件,以满足不同路由的需求。

    总结

    责任链模式是一种行为型设计模式,旨在将请求的发送者和接收者解耦,并通过一系列的处理对象来处理该请求。责任链模式中的每个处理对象都有机会处理请求,并可以将请求传递给下一个处理对象,直到有一个对象能够真正处理请求为止。

    通过责任链模式,可以实现请求的分发和处理的解耦,以及灵活地组织和修改处理器链。这种模式有几个关键点:

    1. 请求发送者和接收者的解耦:请求发送者不需要知道最终哪个对象将处理请求,而处理者也不需要知道请求的发送者是谁,彼此之间解耦。
    2. 多个对象有机会处理请求:责任链模式可以将请求传递给一系列的处理对象,以便其中一个对象能够处理请求。每个处理对象有机会处理请求,也可以选择将请求传递给下一个对象。
    3. 动态修改处理器链:可以根据需要添加、移除或重新排序链中的处理对象,以满足不同的需求。这种灵活性使得责任链模式适用于处理复杂的请求处理流程。
    4. 可以避免耦合和冗余代码:每个处理器只需关注自己的职责,将请求传递给下一个处理器,从而避免了处理器之间的直接耦合和冗余的重复代码。

    Web框架中的请求处理逻辑可以使用责任链模式来实现,例如Echo和Gin框架。在这些框架中,请求首先经过一系列的中间件,每个中间件代表责任链模式的一个处理对象,可以执行通用的逻辑或对请求进行预处理,然后将请求传递给下一个中间件。最后,请求到达路由处理函数,进行实际的业务逻辑处理。

    总之,责任链模式通过将请求的发送者和接收者解耦,并形成一条处理器链,将请求沿着链传递,使得多个处理对象有机会处理请求,实现了请求的分发和处理的灵活性和可扩展性。这种模式在很多场景下都能派上用场,特别是在处理复杂的请求流程或者需要动态修改处理流程的情况下。

    相关文章

      网友评论

          本文标题:责任链模式

          本文链接:https://www.haomeiwen.com/subject/cvexbdtx.html