Chain of Responsibility Pattern in Go Design Patterns

Yuxian: CSDN content partner, CSDN new star mentor, full-stack creative star creator, 51CTO (Top celebrity + expert blogger), github open source enthusiast (go-zero source code secondary development, game back-end architecture https: https://github.com/Peakchen)

           

 

Detailed explanation of the principle of the chain of responsibility pattern:
Chain of Responsibility Pattern (Chain of Responsibility Pattern) is a behavioral design pattern used to decouple the relationship between the sender and the receiver. In the Chain of Responsibility pattern, multiple objects form a chain of responsibility, and each object has the opportunity to process the request. If the current object cannot process the request, it will pass the request to the next object until the request is processed or the chain ends.

The core idea of ​​the chain of responsibility pattern is to decouple the sender and receiver of the request, so that multiple objects have the opportunity to process the request. Requests are passed along the chain of responsibility, and each object can choose to handle the request or pass it on to the next object. This allows flexible organization and extension of the object's processing logic while avoiding direct coupling between sender and receiver.

Underlying structure diagram:
The following is a classic structure diagram of the chain of responsibility model:

+-------------------+
|    Handler        |
+-------------------+
| - successor       |
| + HandleRequest() |
+-------------------+

        ^
        |
        |
        |
        |
        v

+-------------------+
|   ConcreteHandler |
+-------------------+
| + HandleRequest() |
+-------------------+

In the above structure diagram, Handler it is an abstract processor, which defines the interface for processing requests and contains a reference to the next processor  successor. A handler can choose to process the request, or pass the request to the next handler.

ConcreteHandler Is the specific handler, inherited from  Handler, and implements the specific logic for processing requests. In  HandleRequest() the method, the specific processor judges whether he can process the request, and if it can process it, process the request; otherwise, pass the request to the next processor.

Scenario Explanation:
The Chain of Responsibility pattern is applicable to the following scenarios:

  1. The Chain of Responsibility pattern can be used when there are multiple objects that can handle the same request, but which object needs to be determined at runtime. The Chain of Responsibility pattern allows to dynamically organize the sequence of processors, and the sender does not need to know who the final recipient is.

  2. The Chain of Responsibility pattern can be used when one wishes to avoid a direct coupling relationship between sender and receiver. The Chain of Responsibility pattern decouples the sender and receiver, and each processor only needs to focus on its own logic without knowing the existence of other processors.

  3. The Chain of Responsibility pattern can be used when there is a need for flexibility in adding, removing, or reordering between different processors. The Chain of Responsibility pattern allows dynamic adjustment of the processor's organizational structure, thereby achieving a more flexible processing flow.

Code example implementation:
The following is an example of implementing the Chain of Responsibility pattern in Go language:

package main

import "fmt"

// Handler 抽象处理者
type Handler interface {
	SetSuccessor(successor Handler)
	HandleRequest(request int)
}

// ConcreteHandler 具体处理者
type ConcreteHandler struct {
	successor Handler
}

// SetSuccessor 设置下一个处理者
func (h *ConcreteHandler) SetSuccessor(successor Handler) {
	h.successor = successor
}

// HandleRequest 处理请求
func (h *ConcreteHandler) HandleRequest(request int) {
	if request >= 0 && request < 10 {
		fmt.Printf("ConcreteHandler handles request: %d\n", request)
	} else if h.successor != nil {
		h.successor.HandleRequest(request)
	} else {
		fmt.Println("No handler can handle the request")
	}
}

func main() {
	handler1 := &ConcreteHandler{}
	handler2 := &ConcreteHandler{}
	handler3 := &ConcreteHandler{}

	handler1.SetSuccessor(handler2)
	handler2.SetSuccessor(handler3)

	requests := []int{1, 5, 12}

	for _, request := range requests {
		handler1.HandleRequest(request)
	}
}

In the above example, we defined an  Handler interface as an abstract handler, which contains  SetSuccessor() and  HandleRequest() methods. Then, we implemented concrete handlers  and implemented  methods ConcreteHandlerbased on concrete processing logic  .HandleRequest()

In  main() the function, we create three concrete handlers  handler1, handler2 and  handler3, and use  SetSuccessor() methods to connect them in order to form a chain of responsibility. We then define a slice of three requests  requestsand pass each request to the start of the chain of responsibility through a loop  handler1.

Documentation Links:
Here are some links to literature on the Chain of Responsibility pattern to learn more about this design pattern:

  1. A detailed introduction to the Chain of Responsibility pattern in Design Patterns: Elements of Reusable Object -Oriented Software (original title: Design Patterns: Elements of Reusable Object-Oriented Software), a classic in the field of design patterns .

  2. An introduction to the Chain of Responsibility pattern is also included in the book Head First Design Patterns (formerly titled: Head First Design Patterns), which explains various design patterns in an accessible manner.

  3. The Refactoring Guru's Chain of Responsibility pattern article provides detailed explanations, sample code, and application scenarios for the Chain of Responsibility pattern.

Which products are currently in use:
The chain of responsibility pattern is a commonly used design pattern, widely used in software development in various fields. Many software products use the Chain of Responsibility pattern to implement a flexible request-handling process. Here are some common products and frameworks that use the Chain of Responsibility pattern or similar concepts:

  1. The Servlet Filter (Servlet Filter) in Java uses the Chain of Responsibility pattern to process requests.

  2. Interceptors in the Spring framework also use the Chain of Responsibility pattern, allowing custom logic to be executed before and after request processing.

  3. The request processing flow in a web server (such as Apache, Nginx) can also be regarded as an implementation of a chain of responsibility pattern.

  4. Loggers and Log Filters also typically use the Chain of Responsibility pattern to handle different levels of log messages.

Guess you like

Origin blog.csdn.net/feng1790291543/article/details/132160368