【设计模式】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
}
相关推荐
rookie_fly3 小时前
基于Vue的数字输入框指令
前端·vue.js·设计模式
Yeniden4 小时前
【设计模式】# 外观模式(Facade)大白话讲解!
java·设计模式·外观模式
Yeniden4 小时前
【设计模式】 组合模式(Composite)大白话讲解
java·设计模式·组合模式
Damon小智12 小时前
鸿蒙元服务深度实践:跨端唤醒与状态共享的设计模式
华为·设计模式·harmonyos
shaominjin12312 小时前
单例模式:设计模式中的“独一无二“之道
android·单例模式·设计模式
欠你一个bug17 小时前
Java设计模式应用--装饰器模式
java·设计模式·装饰器模式
LoveXming1 天前
Chapter14—中介者模式
c++·microsoft·设计模式·中介者模式·开闭原则
崎岖Qiu1 天前
【设计模式笔记06】:单一职责原则
java·笔记·设计模式·单一职责原则
Yeniden1 天前
【设计模式】适配器模式大白话讲解!
设计模式·适配器模式
金色熊族1 天前
装饰器模式(c++版)
开发语言·c++·设计模式·装饰器模式