Go设计模式(21)-职责链模式

简介: 职责链将处理模块串联成链,请求沿着链条被处理,提供了很好的扩展性,而且能够去掉if-else。

职责链将处理模块串联成链,请求沿着链条被处理,提供了很好的扩展性,而且能够去掉if-else。

UML类图位置:https://www.processon.com/view/link/60d29bf3e401fd49502afd25

本文代码链接为:https://github.com/shidawuhen/asap/blob/master/controller/design/21chain.go

1.定义

1.1职责链模式

职责链模式(Chain of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

UML:

图片

1.2分析

职责链模式的定义已经将模式说的比较清楚了,一个请求需要被多个对象进行处理,可以将处理对象连成一条链,挨个处理请求。

连成链的方式比较多样,可以用UML中展示的那样,一个处理对象使用SetSuccessor引用下一个处理对象。也可以使用array或者list存储所有处理对象,使用循环方式遍历。

对于第二种方式,是否感觉有些像Go设计模式(18)-观察者模式。两者具体实现、目的都差不多,主要区别在观察者模式中的处理对象功能可能完全不相似,而且观察者模式主要负责将信息传递给处理对象即可。职责链模式的处理对象功能一般相似,另外职责链模式也关注请求是否正确被处理。

另外,定义里说”直到有一个对象处理它“也不太准确,有多少对象可以处理请求看具体需求,极端情况下每一个对象都可以处理请求。

职责链模式的核心在于将处理对象整理成链路。

2.应用场景

如果请求被多个对象进行处理,就可以用职责链模式。具体业务的像敏感词脱敏,框架中的过滤器、拦截器等。

总体感觉框架中使用的比较多一些,研发人员能够快速扩展出自己的过滤器和拦截器。

以前写过Gin源码剖析,里面有全局中间件的概念,而全局中间件使用的便是职责链模式。

3.代码实现

我们仿照Gin,实现Gin的全局中间件功能。

package main

import "fmt"

var status int8 = 0

type HandlerFunc func()

type HandlersChain []HandlerFunc

/**
 * @Author: Jason Pang
 * @Description:
 */
type RouterGroup struct {
   Handlers HandlersChain
   index    int8
}

/**
 * @Author: Jason Pang
 * @Description: 添加中间件,将其组成链式
 * @receiver group
 * @param middleware
 */
func (group *RouterGroup) Use(middleware ...HandlerFunc) {
   group.Handlers = append(group.Handlers, middleware...)
}

/**
 * @Author: Jason Pang
 * @Description: 链顺序执行
 * @receiver group
 */
func (group *RouterGroup) Next() {
   for group.index < int8(len(group.Handlers)) {
      group.Handlers[group.index]()
      group.index++
   }
}

/**
 * @Author: Jason Pang
 * @Description: 中间件
 */
func middleware1() {
   fmt.Println("全局中间件1执行完毕")
}

/**
 * @Author: Jason Pang
 * @Description: 中间件
 */
func middleware2() {
   fmt.Println("全局中间件2执行失败")
   status = 1
}

func main() {
   r := &RouterGroup{}
   //添加中间件
   r.Use(middleware1, middleware2)
   //运行中间件
   r.Next()
   //状态检查
   if status == 1 {
      fmt.Println("中间件检查失败,请重试")
      return
   }
   //执行后续流程
}

输出:

➜ myproject go run main.go

全局中间件1执行完毕

全局中间件2执行失败

中间件检查失败,请重试

这是一个简版的中间件执行过程,我将Gin中的Context和RouterGroup合并了。虽然比起真正的执行流程缺乏很多内容,但是核心操作是一致的。

3.总结

通过Gin中间件的例子,可以很好证明职责链的扩展性。简单使用Use增加自己创建的中间件,每一个请求都会被新增的中间件所处理。所以开发者可以方便的增加鉴权、限流、脱敏、拦截等操作。这就是所谓的优雅吧。

最后

大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)

图片

往期文章回顾:

  1. 设计模式
  2. 招聘
  3. 思考
  4. 存储
  5. 算法系列
  6. 读书笔记
  7. 小工具
  8. 架构
  9. 网络
  10. Go语言
相关文章
|
4月前
|
设计模式 JavaScript 前端开发
js设计模式【详解】—— 职责链模式
js设计模式【详解】—— 职责链模式
76 8
|
3月前
|
设计模式 Go
go 设计模式之观察者模式
go 设计模式之观察者模式
|
4月前
|
设计模式 Go
Go语言设计模式:使用Option模式简化类的初始化
在Go语言中,面对构造函数参数过多导致的复杂性问题,可以采用Option模式。Option模式通过函数选项提供灵活的配置,增强了构造函数的可读性和可扩展性。以`Foo`为例,通过定义如`WithName`、`WithAge`、`WithDB`等设置器函数,调用者可以选择性地传递所需参数,避免了记忆参数顺序和类型。这种模式提升了代码的维护性和灵活性,特别是在处理多配置场景时。
72 8
|
5月前
|
设计模式
职责链模式-大话设计模式
职责链模式-大话设计模式
|
5月前
|
设计模式
行为设计模式之职责链模式
行为设计模式之职责链模式
|
6月前
|
设计模式 Go
[设计模式 Go实现] 结构型~享元模式
[设计模式 Go实现] 结构型~享元模式
|
6月前
|
设计模式 Go API
[设计模式 Go实现] 结构型~外观模式
[设计模式 Go实现] 结构型~外观模式
|
6月前
|
设计模式 Go
[设计模式 Go实现] 结构型~组合模式
[设计模式 Go实现] 结构型~组合模式
|
6月前
|
设计模式 Go
[设计模式 Go实现] 结构型~装饰模式
[设计模式 Go实现] 结构型~装饰模式
|
6月前
|
设计模式 Go
[设计模式 Go实现] 行为型~解释器模式
[设计模式 Go实现] 行为型~解释器模式