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

Go语言实现职责链模式:轻松构建中间件
本文介绍了职责链模式,通过UML类图和代码示例展示了如何在Go中实现类似Gin框架的全局中间件功能。职责链模式允许请求被多个对象处理,提供扩展性,常用于框架的过滤器和拦截器。文中提供的代码示例展示了如何创建和执行中间件链,以及如何在链中检查和响应请求状态。

职责链将处理模块串联成链,请求沿着链条被处理,提供了很好的扩展性,而且能够去掉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增加自己创建的中间件,每一个请求都会被新增的中间件所处理。所以开发者可以方便的增加鉴权、限流、脱敏、拦截等操作。这就是所谓的优雅吧。

最后

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

我的个人博客为:https://shidawuhen.github.io/

图片

往期文章回顾:

  1. 设计模式

  2. 招聘

  3. 思考

  4. 存储

  5. 算法系列

  6. 读书笔记

  7. 小工具

  8. 架构

  9. 网络

  10. Go语言

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员麻辣烫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值