Что это такое
Паттерн Chain of Responsibility («цепочка обязанностей») передаёт запрос по цепочке обработчиков. Каждый обработчик либо справляется с запросом сам, либо передаёт его следующему. Отправитель знает только первое звено — и никогда не знает, кто решит задачу на самом деле.
Пример: линия поддержки
Проблема попадает к чат-боту. То, что бот не может исправить, уходит в техподдержку; то, что не может исправить техподдержка, уходит к менеджеру, который решает всё, что до него доходит.
Передаём дальше, пока кто-нибудь не справится
«Нет интернета» проходит один шаг и останавливается на техподдержке; запрос на возврат средств проходит всю цепочку до менеджера. Вызывающий код в обоих случаях написал одну и ту же строку.
Вывод: программа на Go и захваченный вывод
package main
import "fmt"
type Handler struct {
name string
canFix func(problem string) bool
next *Handler
}
func (h *Handler) Handle(problem string) {
if h.canFix(problem) {
fmt.Println(h.name, "решает:", problem)
return
}
fmt.Println(h.name, "передаёт дальше")
if h.next != nil {
h.next.Handle(problem)
}
}
func main() {
manager := &Handler{
name: "менеджер",
canFix: func(p string) bool { return true },
}
tech := &Handler{
name: "техподдержка",
canFix: func(p string) bool { return p == "нет интернета" },
next: manager,
}
bot := &Handler{
name: "чат-бот",
canFix: func(p string) bool { return p == "забыл пароль" },
next: tech,
}
bot.Handle("нет интернета")
fmt.Println("---")
bot.Handle("запрос на возврат средств")
}
Когда это использовать
Используйте, когда запрос могут обработать несколько участников и заранее неизвестно, кто именно подойдёт, — эскалация в поддержке, middleware, обработка событий, процессы согласования.
Не используйте, когда обработчик всегда известен, — вызывайте его напрямую. Цепочка из одного звена или та, что всегда заканчивается на одном и том же звене, — это обычный вызов функции в маскарадном костюме.
Плюсы и минусы
Плюсы: отправитель и получатели развязаны; звенья можно свободно добавлять, удалять и менять местами; каждый обработчик остаётся небольшим.
Минусы: нет гарантии, что запрос вообще кто-то обработает, — сломанная цепочка молча его проглатывает; отслеживать путь запроса через множество звеньев при отладке дольше.