一文搞懂责任链模式

原理

将多个处理器连成一个链条,处理器A处理请求成功后,将请求交给处理器B,处理器B处理成功后再交给处理器C,以此类推,链条上每个处理器各自承担自己的职责。如果处理器处理失败,那么不再继续往后传递处理。

实现方式

方式1

定义IDoHandler接口,业务处理类直接实现该接口实现业务方法,定义一个Handler类,该类持有IDoHandler、Successor,IDoHandler代表具体业务实现,Successor代表下一个Handler;HandlerChain用来表示处理器链条,从数据结构上来说是一个包含头尾指针的链表,链表中的元素就是Handler类

type IDoHandler interface {
	DoHandle()
}

type Handler struct {
	DoHandler IDoHandler
	Successor *Handler
}

func (h *Handler) Handle() {
	handled := true
	h.DoHandler.DoHandle() //执行业务逻辑
	if handled && h.Successor != nil {
		h.Successor.Handle()
	}
}

type HandlerChain struct {
	Head *Handler
	Tail *Handler
}

func (c *HandlerChain) AddHandler(handler *Handler) {
	if c.Head == nil {
		c.Head = handler
		c.Tail = handler
	} else {
		c.Tail.Successor = handler
		c.Tail = handler
	}
}

func (c *HandlerChain) Handle() {
	if c.Head != nil {
		c.Head.Handle()
	}
}

type ADoHandler struct{}

func (h *ADoHandler) DoHandle() {
	println("A Handle")
}

type BDoHandler struct{}

func (h *BDoHandler) DoHandle() {
	println("B Handle")
}

func ApplicationMain() {
	chain := new(HandlerChain)
	aHandler := new(Handler)
	aHandler.DoHandler = new(ADoHandler)
	bHandler := new(Handler)
	bHandler.DoHandler = new(BDoHandler)
	chain.AddHandler(aHandler)
	chain.AddHandler(bHandler)
	chain.Handle()
}

方式2

定义IHandler接口,HandlerChain持有一个IHandler的数组,依次调用数组中的每个子类Handler

type IHandler interface {
	Handle() bool
}

type HandlerChainV2 struct {
	handlerList []IHandler
}

func (c *HandlerChainV2) AddHandler(h IHandler) {
	c.handlerList = append(c.handlerList, h)
}

func (c *HandlerChainV2) Handle() {
	for i := range c.handlerList {
		handled := c.handlerList[i].Handle()
		if handled == false {
			break
		}
	}
}

type AHandler struct{}

func (h *AHandler) Handle() bool {
	println("A Handle")
}

type BHandler struct{}

func (h *BHandler) Handle() bool {
	println("B Handle")
}

func ApplicationMain2() {
	c := new(HandlerChainV2)
	c.AddHandler(new(AHandler))
	c.AddHandler(new(BHandler))
	c.Handle()
}

变体实现

变体定义:不管处理器是否处理成功,都往后传递请求继续处理,不存在中途终止的情况

变体实现思路:实现1不管handled是否为true,只要successor不为nil就继续调用;实现2如果handler处理失败,那么也不需要break,继续往后执行

最佳实践

需求背景

对于支持 UGC(User Generated Content,用户生成内容)的应用(比如论坛)来说,用户生成的内容(比如,在论坛中发表的帖子)可能会包含一些敏感词(比如涉黄、广告、反动等词汇)。针对这个应用场景,我们就可以利用职责链模式来过滤这些敏感词。对于包含敏感词的内容,我们有两种处理方式,一种是直接禁止发布,另一种是给敏感词打马赛克(比如,用 *** 替换敏感词)之后再发布。

第一种处理方式符合 职责链模式的标准定义,第二种处理方式是职责链模式的变体。

第一种处理方式实现

type ISensitiveWordDoFilter interface {
	DoFilter(words string) bool
}

type SensitiveWordFilter struct {
	doFilter ISensitiveWordDoFilter
	next     *SensitiveWordFilter
}

func (f *SensitiveWordFilter) Filter(words string) bool {
	handled := f.doFilter.DoFilter(words)
	if handled && f.next != nil {
		return f.next.Filter(words)
	}
	return handled
}

type SensitiveWordFilterChain struct {
	head *SensitiveWordFilter
	tail *SensitiveWordFilter
}

func (c *SensitiveWordFilterChain) AddFilter(filter *SensitiveWordFilter) {
	if c.head == nil {
		c.head = filter
		c.tail = filter
	} else {
		c.tail.next = filter
		c.tail = filter
	}
}

func (c *SensitiveWordFilterChain) Filter(words string) bool {
	if c.head != nil {
		return c.head.Filter(words)
	}
	return true
}

type SexySensitiveWordDoFilter struct{}

func (f *SexySensitiveWordDoFilter) DoFilter(words string) bool {
	if words == "sexy" {
		return false
	}
	return true
}

type FuckSensitiveWordDoFilter struct{}

func (f *FuckSensitiveWordDoFilter) DoFilter(words string) bool {
	if words == "fuck" {
		return false
	}
	return true
}

func ApplicationMain3(words string) {
	chain := new(SensitiveWordFilterChain)
	sexyFilter := new(SensitiveWordFilter)
	sexyFilter.doFilter = new(SexySensitiveWordDoFilter)
	fuckFilter := new(SensitiveWordFilter)
	fuckFilter.doFilter = new(FuckSensitiveWordDoFilter)
	chain.AddFilter(sexyFilter)
	chain.AddFilter(fuckFilter)
	println(chain.Filter(words))
}

优点

  1. 应对代码复杂度
    把大块逻辑拆成函数,把大类拆小类,是应对代码复杂度的有效手段。采用职责链模式,我们将不同Filter的敏感词过滤逻辑都给抽到了单独的类里面,SensitiveWordFilter类的代码就不会太多太复杂

  2. 满足开闭原则
    当我们需要新增一个新的敏感词过滤逻辑时,只需要定义一个新的Filter即可,然后在客户端代码(使用职责链的代码)添加这个Filter即可,可以将整个代码分为框架部分(职责链部分)和客户端部分,新增Filter时框架部分不需要任何改动,满足开闭原则

  3. 可以灵活地选择需要的Filter

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值