责任链模式

责任链模式的概念

责任链模式是一种行为设计模式,它允许多个对象有机会处理请求,从而避免请求的发送者和接收者之间的耦合。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

责任链模式作用

减少请求的发送者和接收者之间的耦合。

可以动态地增加或修改处理请求的算法。

可以将请求传递给多个对象中的一个,而不需要明确指定接收者。

责任链模式应用场景

有多个对象可以处理一个请求,但具体由哪个对象处理在运行时才能确定。

你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。

可处理一个请求的对象集合应被动态指定。

Go 语言实现责任链模式的例子

下面是一个简单的责任链模式的例子,模拟一个请假审批流程,不同级别的领导可以审批不同天数的请假请求。

package main

import (
	"fmt"
)

// 1. 定义处理请求的接口
type Approver interface {
	SetNext(approver Approver)
	Approve(request *LeaveRequest)
}

// 2. 定义请假请求结构体
type LeaveRequest struct {
	Name     string
	Days     int
	Approved bool
}

// 3.1 定义具体的处理者:经理
type Manager struct {
	next Approver
}
func (m *Manager) SetNext(approver Approver) {
	m.next = approver
}
func (m *Manager) Approve(request *LeaveRequest) {
	if request.Days <= 3 {
		fmt.Printf("Manager approved %s's leave for %d days.\n", request.Name, request.Days)
		request.Approved = true
	} else if m.next != nil {
		m.next.Approve(request)
	} else {
		fmt.Printf("Manager cannot approve %s's leave for %d days.\n", request.Name, request.Days)
	}
}

// 3.2 定义具体的处理者:总监
type Director struct {
	next Approver
}
func (d *Director) SetNext(approver Approver) {
	d.next = approver
}
func (d *Director) Approve(request *LeaveRequest) {
	if request.Days <= 7 {
		fmt.Printf("Director approved %s's leave for %d days.\n", request.Name, request.Days)
		request.Approved = true
	} else if d.next != nil {
		d.next.Approve(request)
	} else {
		fmt.Printf("Director cannot approve %s's leave for %d days.\n", request.Name, request.Days)
	}
}

// 3.3 定义具体的处理者:CEO
type CEO struct{}
func (c *CEO) SetNext(approver Approver) {
	// CEO 是最高级别的审批者,没有下一个审批者
}
func (c *CEO) Approve(request *LeaveRequest) {
	if request.Days <= 30 {
		fmt.Printf("CEO approved %s's leave for %d days.\n", request.Name, request.Days)
		request.Approved = true
	} else {
		fmt.Printf("CEO cannot approve %s's leave for %d days.\n", request.Name, request.Days)
	}
}

func main() {
	// 创建审批者链
	manager := &Manager{}
	director := &Director{}
	ceo := &CEO{}

	manager.SetNext(director)
	director.SetNext(ceo)

	// 创建请假请求
	request1 := &LeaveRequest{Name: "Alice", Days: 2}
	request2 := &LeaveRequest{Name: "Bob", Days: 5}
	request3 := &LeaveRequest{Name: "Charlie", Days: 10}
	request4 := &LeaveRequest{Name: "David", Days: 25}
	request5 := &LeaveRequest{Name: "Eve", Days: 35}

	// 提交请假请求
	manager.Approve(request1)
	manager.Approve(request2)
	manager.Approve(request3)
	manager.Approve(request4)
	manager.Approve(request5)
}