什么是责任链
责任链模式允许开发者将请求沿着链进行发送,直至其中一个处理者对象对其进行处理。 责任链模式可以将请求的发送者和接收者解耦
责任链模式允许多个处理者对象对请求进行处理,无须让发送者类与具体的接收者类相耦合
组成:
- 处理者(handler): 声明所有具体处理者类的通用接口。该接口通常仅包含一个方法,用于处理请求,但有时还会包含一个用于设置下一个具体处理者对象的方法
- 基础处理者(BaseHandler): 一个可选的类,开发者可以将所有处理者对象共用的样本代码放置在其中
- 具体处理者(ConcreteHandler): 包含处理请求实际代码的类。每个具体处理者对象在接收到请求后,都必须决定是否进行处理,以及是否沿着链传递
- 客户端(Client): 可以根据程序逻辑处理一次性或者动态的生成链,请求可以发送给链中的任意一个处理者对象,不一定是第一个处理者对象
代码实现
package main
import "fmt"
/*
定义处理者接口及其处理请求方法,确定客户端如何将请求传递给方法
*/
type Handler interface {
SetNext(handler Handler)
Handle(HandlerID int) int
}
// BaseHandler 基础处理者及其方法
type BaseHandler struct {
name string
next Handler
HandlerID int
}
func NewBaseHandler(name string, next Handler, handlerID int) Handler {
return &BaseHandler{
name: name,
next: next,
HandlerID: handlerID,
}
}
// Handle 处理指定的handleID
func (bh *BaseHandler) Handle(handleID int) int {
if handleID < 4 {
ch := &ConcreteHandler{}
ch.Handle(handleID)
if bh.next != nil {
bh.next.Handle(handleID + 1)
}
return handleID + 1
}
return 0
}
// SetNext 设置下一个处理者对象
func (bh *BaseHandler) SetNext(handler Handler) {
bh.next = handler
}
/*
定义具体处理者类和方法
*/
type ConcreteHandler struct {
}
func (ch *ConcreteHandler) Handle(handleID int) {
fmt.Println("ConcreteHandler handleID:", handleID)
}
func main() {
barry := NewBaseHandler("Barry", nil, 1)
whj := NewBaseHandler("whj", barry, 2)
handleID1 := barry.Handle(1)
barry.SetNext(whj)
fmt.Println(handleID1)
}
使用场景
- 如果程序需要使用不同的方式处理不同种类的请求,并且请求类型和顺序预先未知,则可以使用责任链模式
- 如果必须按照顺序执行多个具体处理者对象,则可以使用责任链模式
- 如果所需的具体处理者对象及其顺序必须在运行时发生改变,则可以使用责任链模式
优缺点
优点
- 可以控制处理的顺序
- 符合单一职责
- 符合开闭原则
- 可以简化对象,对象不需要知道链结构
缺点
- 部分请求可能未被处理
- 可能造成循环调用
- 不易调试
- 增加维护成本(可能会出现重复代码)