【设计模式】15、chain of responsibility 责任链模式

文章目录

  • [十五、chain of responsibility 责任链](#十五、chain of responsibility 责任链)
    • [15.1 oa 审批系统](#15.1 oa 审批系统)
      • [15.1.1 oa_test.go](#15.1.1 oa_test.go)
      • [15.1.2 oa.go](#15.1.2 oa.go)
      • [15.1.3 step.go](#15.1.3 step.go)
    • [15.2 敏感词过滤器](#15.2 敏感词过滤器)
      • [15.2.1 filter_test.go](#15.2.1 filter_test.go)
      • [15.2.2 filter.go](#15.2.2 filter.go)

十五、chain of responsibility 责任链

https://refactoringguru.cn/design-patterns/chain-of-responsibility

如果需按顺序, 执行一系列步骤, 可用责任链.

链条上的每个步骤, 都持有下一个步骤的引用, 当自身步骤执行完毕后, 执行下一个步骤.

在运行时, client 也可以主动编辑 链的顺序.

核心是, 各步骤都实现相同的接口.

15.1 oa 审批系统

公司有流程申请系统, 员工的申请, 需要逐层审批. 是典型的链式.

基层员工, 先 HR 审批, 再 TL 审批, 再 BOSS 审批

bash 复制代码
├── oa.go
├── oa_test.go
├── readme.md
└── step.go

15.1.1 oa_test.go

go 复制代码
package _51oa

import (
    "fmt"
    "testing"
)

/*
=== RUN   TestOAStep
流程开始
[hrStep] 开始审批
开始处理
[tlStep] 开始审批
开始处理
[bossStep] 开始审批
开始处理
流程结束
--- PASS: TestOAStep (0.00s)
PASS
*/
func TestOAStep(t *testing.T) {
    o := NewOA()
    fmt.Println("流程开始")
    o.approval()
    fmt.Println("流程结束")
}

15.1.2 oa.go

go 复制代码
package _51oa

type oa struct {
    firstStep iStep
}

func NewOA() *oa {
    hr := &hrStep{}
    tl := &tlStep{}
    boss := &bossStep{}

    hr.setNext(tl)
    tl.setNext(boss)
    boss.setNext(nil)

    return &oa{
        firstStep: hr,
    }
}

// 审批
func (o *oa) approval() {
    o.firstStep.handle()
}

15.1.3 step.go

go 复制代码
package _51oa

import (
    "fmt"
)

// iStep 是步骤
type iStep interface {
    // 处理
    handle()
    // 设置下一步骤
    setNext(iStep)
}

// 基本步骤, 是基类, 实现通用方法
type baseStep struct {
    // 链上的下一节点
    next iStep
}

// 各具体实现, 可复用的方法
func (s *baseStep) handle() {
    fmt.Println("开始处理")
    if s.next != nil { // 本步骤执行结束后, 传递给下一步骤继续处理
        s.next.handle()
    }
}

// 各具体实现, 可复用的方法
func (s *baseStep) setNext(nxt iStep) {
    s.next = nxt
}

// hr步骤
type hrStep struct {
    baseStep
}

// 重写方法
func (s *hrStep) handle() {
    fmt.Println("[hrStep] 开始审批")
    s.baseStep.handle()
}

// tl步骤
type tlStep struct {
    baseStep
}

func (s *tlStep) handle() {
    fmt.Println("[tlStep] 开始审批")
    s.baseStep.handle()
}

// boss步骤
type bossStep struct {
    baseStep
}

func (s *bossStep) handle() {
    fmt.Println("[bossStep] 开始审批")
    s.baseStep.handle()
}

15.2 敏感词过滤器

如果希望做一个论坛, 由于法律, 广告等原因, 需要敏感词过滤, 如果含敏感词, 则帖子会被封禁

其实各 filter 构成了职责链

bash 复制代码
├── filter.go
├── filter_test.go
└── readme.md

15.2.1 filter_test.go

go 复制代码
package _52sensitive_word_filter

import (
	"github.com/stretchr/testify/require"
	"testing"
)

/*
=== RUN   TestFilter
执行广告过滤
执行广告过滤
执行法律过滤
--- PASS: TestFilter (0.00s)
PASS
*/
func TestFilter(t *testing.T) {
	chain := SensitiveWordFilterChain{}
	chain.AddFilter(&AdFilter{})
	ret := chain.Filter("abc")
	require.True(t, ret)

	chain.AddFilter(&PoliceFilter{})
	ret = chain.Filter("abc")
	require.True(t, ret)
}

15.2.2 filter.go

go 复制代码
package _52sensitive_word_filter

import "fmt"

// SensitiveWordFilter 过滤器接口
type SensitiveWordFilter interface {
	Filter(content string) bool
}

// SensitiveWordFilterChain 职责链
type SensitiveWordFilterChain struct {
	filters []SensitiveWordFilter
}

func (c *SensitiveWordFilterChain) AddFilter(f SensitiveWordFilter) {
	c.filters = append(c.filters, f)
}

func (c *SensitiveWordFilterChain) Filter(content string) bool {
	for _, f := range c.filters {
		f.Filter(content)
	}
	return true
}

// AdFilter 广告过滤器
type AdFilter struct{}

func (f *AdFilter) Filter(content string) bool {
	fmt.Println("执行广告过滤")
	return true
}

// PoliceFilter 法律过滤器
type PoliceFilter struct{}

func (f *PoliceFilter) Filter(content string) bool {
	fmt.Println("执行法律过滤")
	return true
}
相关推荐
WaaTong44 分钟前
《重学Java设计模式》之 原型模式
java·设计模式·原型模式
霁月风1 小时前
设计模式——观察者模式
c++·观察者模式·设计模式
暗黑起源喵3 小时前
设计模式-工厂设计模式
java·开发语言·设计模式
wrx繁星点点11 小时前
状态模式(State Pattern)详解
java·开发语言·ui·设计模式·状态模式
金池尽干12 小时前
设计模式之——观察者模式
观察者模式·设计模式
也无晴也无风雨13 小时前
代码中的设计模式-策略模式
设计模式·bash·策略模式
捕鲸叉1 天前
MVC(Model-View-Controller)模式概述
开发语言·c++·设计模式
wrx繁星点点1 天前
享元模式:高效管理共享对象的设计模式
java·开发语言·spring·设计模式·maven·intellij-idea·享元模式
凉辰1 天前
设计模式 策略模式 场景Vue (技术提升)
vue.js·设计模式·策略模式
菜菜-plus1 天前
java设计模式之策略模式
java·设计模式·策略模式