GO设计模式——15、责任链模式(行为型)

目录

[责任链模式(Chain of Responsibility Pattern)](#责任链模式(Chain of Responsibility Pattern))

责任链模式的核心角色:

优缺点

使用场景

代码实现


责任链模式(Chain of Responsibility Pattern)

责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链将请求的发送者和接收者解耦,并允许多个对象都有机会处理请求。通过为多个对象构成一个链,并将请求沿着这条链传递,直到有一个对象处理请求为止。在责任链模式中,客户只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递过程,请求会自动进行传递。所以责任链将请求的发送者和请求的处理者解耦了。

责任链模式的核心角色

  • 抽象处理者(Handler):定义了处理请求的接口,通常包含一个指向下一个处理者的引用。
  • 具体处理者(Concrete Handler):实现了抽象处理者接口,负责处理请求,如果自己不能处理,则将请求传递给下一个处理者

优缺点

(1)优点:

  • 降低耦合度。它将请求的发送者和接收者解耦。
  • 简化了对象。使得对象不需要知道链的结构。
  • 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
  • 增加新的请求处理类很方便。

(2)缺点:

  • 不能保证请求一定被接收。
  • 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
  • 可能不容易观察运行时的特征,有碍于除错。

使用场景

  • 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
  • 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
  • 可动态指定一组对象处理请求。

代码实现

Go 复制代码
package main

// 请假审批系统,员工可以提交请假申请,申请会依次经过部门经理、人事部门和总经理的审批。
// 如果其中任何一个审批者同意了请假申请,审批流程就结束,否则继续传递给下一个审批者。
import "fmt"

// 抽象处理者:审批者接口
type Approver interface {
    SetNext(approver Approver)
    ProcessRequest(request Request)
}

// 具体处理者:部门经理
type DepartmentManager struct {
    next Approver
}

func (dm *DepartmentManager) SetNext(approver Approver) {
    dm.next = approver
}

func (dm *DepartmentManager) ProcessRequest(request Request) {
    if request.Type == "Leave" && request.Amount <= 3 {
       fmt.Println("Department Manager approved the request.")
    } else if dm.next != nil {
       dm.next.ProcessRequest(request)
    }
}

// 具体处理者:人事部门
type HRDepartment struct {
    next Approver
}

func (hr *HRDepartment) SetNext(approver Approver) {
    hr.next = approver
}

func (hr *HRDepartment) ProcessRequest(request Request) {
    if request.Type == "Leave" && request.Amount <= 7 {
       fmt.Println("HR Department approved the request.")
    } else if hr.next != nil {
       hr.next.ProcessRequest(request)
    }
}

// 具体处理者:总经理
type GeneralManager struct {
    next Approver
}

func (gm *GeneralManager) SetNext(approver Approver) {
    gm.next = approver
}

func (gm *GeneralManager) ProcessRequest(request Request) {
    if request.Type == "Leave" && request.Amount <= 10 {
       fmt.Println("General Manager approved the request.")
    } else {
       fmt.Println("Request denied.")
    }
}

// 请求结构体
type Request struct {
    Type   string
    Amount int
}

// 客户端代码
func main() {
    departmentManager := &DepartmentManager{}
    hrDepartment := &HRDepartment{}
    generalManager := &GeneralManager{}

    departmentManager.SetNext(hrDepartment)
    hrDepartment.SetNext(generalManager)

    request := Request{
       Type:   "Leave",
       Amount: 5,
    }

    departmentManager.ProcessRequest(request)
}
相关推荐
LucianaiB1 天前
【程序员副业指南】KwaiKAT AI制作小红薯📕卡片MCP
后端
成钰1 天前
设计模式之抽象工厂模式:最复杂的工厂模式变种
java·设计模式·抽象工厂模式
IT_陈寒1 天前
Redis性能翻倍的5个冷门优化技巧,90%的开发者都不知道第3个!
前端·人工智能·后端
阿琦学代码1 天前
Spring Cloud(微服务) 概述
后端·spring·spring cloud
GreatSQL1 天前
GreatSQL CTE 查询报告临时表找不到问题解析
后端
用户68545375977691 天前
🎛️ JVM调优秘籍:把你的Java程序调教成性能怪兽!
后端
Asthenia04121 天前
一次空值查询的“陷阱”排查:为什么我的接口不返回数据了?
后端
回家路上绕了弯1 天前
慢查询优化全攻略:从定位根源到落地见效的实战指南
后端·性能优化
长存祈月心1 天前
Rust HashSet 与 BTreeSet深度剖析
开发语言·后端·rust
长存祈月心1 天前
Rust BTreeMap 红黑树
开发语言·后端·rust