【Go-设计模式】职责链模式 详解

shadowLogo

概念:

职责链模式 用于 分离不同职责,并且 动态组合相关职责

职责链模式(Chain of Responsibility Pattern), 又叫 责任链模式,为 请求 创建了 一个接收者对象的链
这种模式对 请求的发送者接收者 进行解耦

通常 每个接收者 都包含 对另一个接收者的引用

如果 一个对象不能处理该请求,那么它会把 相同的请求 传给 下一个接收者,依此类推

这种类型的设计模式属于 行为型模式

职责链


UML:

uml

  • Handler
    抽象的处理器, 定义了一个 处理请求的接口, 同时含有 另外 Handler
  • ConcreteHandler
    具体的处理器,处理它 自己负责的请求, 可以 访问它的后继者(即:下一个处理者), 如果可以处理当前请求,则处理;
    否则,就将该请求交个 后继者 去处理,从而形成一个 职责链
  • Request
    表示一个请求,包含很多属性

示例:

请求信息类:

type Request struct {
	Attri1 int64
	Attri2 string
}

func NewRequest(attri1 int64, attri2 string) Request {
	return Request{
		Attri1: attri1,
		Attri2: attri2,
	}
}

抽象的 处理器接口:

type Handler interface {
	GetSuccessor() Handler
	ProcessRequest(req *Request)
}

具体的处理器类:

具体的处理器1:

type ConcreteHandler1 struct {
	Successor Handler
}

func (this ConcreteHandler1) GetSuccessor() Handler {
	return this.Successor
}

func (this ConcreteHandler1) ProcessRequest(req *Request) {
	fmt.Println("handler1处理了request,处理的request为:", req)
	req.Attri1 += 233
}

func NewConcreteHandler1() *ConcreteHandler1 {
	return &ConcreteHandler1{}
}

具体的处理器2:

type ConcreteHandler2 struct {
	Successor Handler
}

func (this ConcreteHandler2) GetSuccessor() Handler {
	return this.Successor
}

func (this ConcreteHandler2) ProcessRequest(req *Request) {
	fmt.Println("handler2处理了request,处理的request为:", req)
	req.Attri2 = fmt.Sprintf("%s-经过了处理器2的处理", req.Attri2)
	this.GetSuccessor().ProcessRequest(req)
}

func NewConcreteHandler2(successor Handler) *ConcreteHandler2 {
	return &ConcreteHandler2{
		Successor: successor,
	}
}

测试:

package main

import (
	"DemoProject/design/base23/chain"	// 根据自己的项目路径定制
	"fmt"
)

func main() {
	// chain
	handler1 := chain.NewConcreteHandler1()
	handler2 := chain.NewConcreteHandler2(handler1)
	request := chain.NewRequest(0, "目标请求内容")
	handler2.ProcessRequest(&request)
	fmt.Println(request)
}

注意事项:

优点:

请求处理 分开,实现解耦,提高 系统的灵活性

简化了对象,使对象不需要知道 链的具体结构

缺点:

性能 会受到影响,特别是在链比较长的时候,因此需控制 链中最大节点数量,一般通过在 Handler 中设置一个 最大节点数量,在 setNext()方法中判断是否已经 超过阀值超过不允许该链建立,避免出现 超长链 无意识地 破坏系统性能

调试不方便
采用了类似 递归 的方式,调试时逻辑可能比较复杂

应用场景:

多个对象 可以 处理同一个请求
比如:

  • 多级请求
  • 请假/加薪等审批流程
  • 拦截器

在很多 中间件框架 设计中,就使用了 责任链模式

posted @ 2021-12-17 16:04  在下右转,有何贵干  阅读(76)  评论(0)    收藏  举报