【设计模式】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
}
相关推荐
春风十里不如你95272 小时前
【设计模式】【结构型模式(Structural Patterns)】之代理模式(Proxy Pattern)
设计模式·代理模式
请你打开电视看看6 小时前
观察者模式
java·观察者模式·设计模式
Mr.朱鹏6 小时前
设计模式之策略模式-工作实战总结与实现
java·spring·设计模式·kafka·maven·策略模式·springbbot
春风十里不如你95276 小时前
【设计模式】【结构型模式(Structural Patterns)】之组合模式(Composite Pattern)
设计模式·组合模式
捕鲸叉7 小时前
C++设计模式之组合模式实践原则
c++·设计模式·组合模式
阿熊不会编程7 小时前
【计网】自定义协议与序列化(一) —— Socket封装于服务器端改写
linux·开发语言·网络·c++·设计模式
春风十里不如你95277 小时前
【设计模式】【行为型模式(Behavioral Patterns)】之责任链模式(Chain of Responsibility Pattern)
java·设计模式·责任链模式
博风8 小时前
设计模式:11、迭代器模式(游标)
设计模式·迭代器模式
春风十里不如你95279 小时前
【设计模式】【行为型模式(Behavioral Patterns)】之命令模式(Command Pattern)
设计模式·命令模式
岳轩子12 小时前
23种设计模式之原型模式
设计模式·原型模式