简介
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它通过一系列处理者(处理对象)来逐步处理请求,直到请求被处理为止。每个处理者都包含了处理请求的逻辑,并且知道下一个处理者是谁。
责任链模式涉及到以下几个主要角色:
处理者(Handler)
定义了一个处理请求的接口,通常包含一个处理方法,同时包含一个指向下一个处理者的引用。
具体处理者(ConcreteHandler)
实现了处理者接口,负责处理特定类型的请求。如果自己能够处理,则处理请求,否则将请求传递给下一个处理者。
客户端(Client)
创建请求,并将请求发送给第一个处理者。
比如今天无论如何要去买车,但是你身上只有那么点钱,根据金额,先去看BWN,再去看BenZ,最后看Mazda,如果前面都没看到合适价位的,你今天就error了。 ps:感觉这个例子不太好,如果改为线上宕机了,损失几个爽,要背锅了,先从总监->组长->运维->你,一路追责下来,这个例子好点。没办法,我就是喜欢车。
Demo
// Handler 处理者接口
type Handler interface {
HandleRequest(amount int)
SetSuccessor(successor Handler)
}
// CarHandler 购车处理者,具体处理者
type CarHandler struct {
Price int
Car string
successor Handler
}
func (c *CarHandler) HandleRequest(price int) {
if price >= c.Price {
fmt.Printf("你的金额为:%d,你可以买 %s\n", price, c.Car)
} else if c.successor != nil {
fmt.Printf("你的金额为:%d, 你不能买 %s\n ", price, c.Car)
fmt.Printf("不过我们可以看看下一个你可以买的车.\n")
c.successor.HandleRequest(price)
} else {
fmt.Printf("Sorry, 你的金额%d,买不了任何车,这边建议你买电动车\n", price)
}
}
func (c *CarHandler) SetSuccessor(successor Handler) {
c.successor = successor
}
测试
func TestResponsibilityChain(t *testing.T) {
// 客户端使用责任链模式
bmwHandler := &CarHandler{Price: 200000, Car: "BMW"}
benzHandler := &CarHandler{Price: 150000, Car: "Benz"}
mazdaHandler := &CarHandler{Price: 100000, Car: "Mazda"}
noCarHandler := &CarHandler{Price: 0, Car: "no car"}
// 设置处理者的后继关系
bmwHandler.SetSuccessor(benzHandler)
benzHandler.SetSuccessor(mazdaHandler)
mazdaHandler.SetSuccessor(noCarHandler)
// 模拟用户输入不同的金额
amounts := []int{180000, 220000, 120000, 80000}
for _, amount := range amounts {
// 通过责任链传递请求
bmwHandler.HandleRequest(amount)
fmt.Println("---------------------")
}
}
在这个示例中,每个 CarHandler 表示一种车的购买条件,包括金额阈值和车型。客户端创建了一条责任链,连接了购买不同车型的处理者。当用户输入不同的金额时,责任链会逐步判断是否满足购车条件,如果不满足,则请求会被传递给下一个处理者。最终,用户会得知根据输入金额能否购买某种车型。
这种设计模式使得条件判断和处理逻辑更具灵活性,可以动态添加或修改购车条件,而不需要修改客户端的代码。
作用和场景
解耦发送者和接收者
责任链模式可以将请求的发送者和接收者解耦,每个处理者只关心自己能否处理该请求,而不需要知道请求的具体来源和去向。比如我只需要录入金额,然后就分别去判断可以买什么东西。
动态建立责任链
可以动态地建立责任链,根据实际情况来灵活配置处理者的顺序和组合。这使得系统更具扩展性,可以根据需要动态添加、移除或修改处理者。
支持单一职责原则
责任链模式可以使得每个处理者只负责一个明确的责任,符合单一职责原则。这样可以使系统更易于理解和维护
当一个请求可以被多个对象处理,但处理者之间具有不同的优先级或处理条件时,可以使用责任链模式。
当发送者和接收者之间不希望直接耦合时,可以使用责任链模式。
当责任链的组成部分需要动态地配置或改变顺序时,责任链模式可以提供灵活性。
当希望每个处理者只负责一个明确的责任,以支持单一职责原则时,可以使用责任链模式。
总体而言,责任链模式适用于多个对象处理同一类型的请求,且请求的处理顺序和条件可能动态变化的情况。