设计模式-18-职责链模式

责任链模式是一种行为设计模式, 允许你将请求沿着处理者链进行发送。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者

逻辑结构

Chain

代码实现

代码路径:https://github.com/XBoom/DesignPatterns/tree/main/17_Chain

  1. 首先,定义一个请求接口

    1
    2
    3
    4
    5
    // Request 请求接口
    type Request interface {
    GetLevel() int
    GetContent() string
    }
  2. 定义一个处理者接口 Handler,该接口定义了处理请求的方法

    1
    2
    3
    4
    5
    // Handler 处理者接口
    type Handler interface {
    HandleRequest(request Request)
    SetNext(handler Handler)
    }
  3. 具体处理类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    // ConcreteHandler 具体处理者类
    type ConcreteHandler struct {
    level int
    next Handler
    }

    func NewConcreteHandler(level int) *ConcreteHandler {
    return &ConcreteHandler{
    level: level,
    }
    }

    func (h *ConcreteHandler) HandleRequest(request Request) {
    if request.GetLevel() == h.level {
    fmt.Printf("Handler%d 处理请求:%s\n", h.level, request.GetContent())
    } else if h.next != nil {
    h.next.HandleRequest(request)
    } else {
    fmt.Println("没有合适的处理者处理该请求")
    }
    }

    func (h *ConcreteHandler) SetNext(handler Handler) {
    h.next = handler
    }
  4. 最后,定义具体的处理者结构体,实现 Handler 接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // ConcreteRequest 具体请求类
    type ConcreteRequest struct {
    level int
    content string
    }

    func NewConcreteRequest(level int, content string) *ConcreteRequest {
    return &ConcreteRequest{
    level: level,
    content: content,
    }
    }

    func (r *ConcreteRequest) GetLevel() int {
    return r.level
    }

    func (r *ConcreteRequest) GetContent() string {
    return r.content
    }

运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
handler1 := NewConcreteHandler(1)
handler2 := NewConcreteHandler(2)
handler3 := NewConcreteHandler(3)

handler1.SetNext(handler2)
handler2.SetNext(handler3)

request1 := NewConcreteRequest(2, "请求 1")
request2 := NewConcreteRequest(3, "请求 2")
request3 := NewConcreteRequest(1, "请求 3")

handler1.HandleRequest(request1)
handler1.HandleRequest(request2)
handler1.HandleRequest(request3)

结果

1
2
3
Handler2 处理请求:请求 1
Handler3 处理请求:请求 2
Handler1 处理请求:请求 3

错误处理

错误处理也是一种类似职责链的逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
type check struct {
err error
}

func (c check) checkName(name string) check {
if c.err != nil {
if len(name) < 0 {
c.err = errors.New("name length wrong")
return c
}
}
return check{}
}

func (c check) checkAge(age uint8) check {
if c.err != nil {
if age > 200 {
c.err = errors.New("age wrong")
return c
}
}
return check{}
}

func main() {
c := check{}
c := c.checkName("hello").checkAge(18)
if c.err != nil {
//....
}
}

Functiton Option

Function Option 也算是一种职责链模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
type Person struct {
name string
age int
gender string
}

type Option func(*Person)

func WithName(name string) Option {
return func(p *Person) {
p.name = name
}
}

func WithAge(age int) Option {
return func(p *Person) {
p.age = age
}
}

func WithGender(gender string) Option {
return func(p *Person) {
p.gender = gender
}
}

func NewPerson(opts ...Option) *Person {
p := &Person{}
for _, opt := range opts {
opt(p)
}
return p
}

函数选项模式可以实现一些类似职责链的行为,但它并不是职责链模式的直接实现。职责链模式更加注重请求的传递和处理过程,通常涉及多个处理者的协作,而函数选项模式主要用于对象构造和定制

总结

  • 可以控制请求处理的顺序,
  • 单一职责原则。 可对发起操作和执行操作的类进行解耦
  • 开闭原则。 可以在不更改现有代码的情况下在程序中新增处理者
  • 当职责链过长,可能需要遍历整个链才能被处理
  • 适用于异常处理链、权限验证等

参考链接

  1. https://refactoringguru.cn/design-patterns/chain-of-responsibility
  2. https://lailin.xyz/post/chain.html
  3. https://time.geekbang.org/column/article/330212
  4. https://time.geekbang.org/column/article/330207