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)
}
相关推荐
Moe48816 小时前
Spring AI Advisors:从链式增强到递归顾问
java·后端
37手游后端团队17 小时前
Claude Code 指南:终端 AI 编程助手的正确打开方式
人工智能·后端
H_老邪17 小时前
spring boot 学习之路-1.0
spring boot·后端·学习
树獭叔叔18 小时前
Claude Code Skill 系统:懒加载的 Agent 行动说明
后端·aigc·openai
Nexzk18 小时前
我把 Hermes Agent 源码扒了个底朝天:它不是“又一个 AI Agent”,而是在认真造一套代理操作系统
后端
袋鱼不重18 小时前
Hermes Agent 安装与实战:从安装到与 OpenClaw 全方位对比
前端·后端·ai编程
写Cpp的小黑黑18 小时前
C++ std::shared_ptr 线程安全性和最佳实践详解
后端
沸点小助手18 小时前
「 AI 整活大赛,正式开擂 & 最近一次面试被问麻了吗」沸点获奖名单公示|本周互动话题上新🎊
前端·人工智能·后端
何陋轩18 小时前
消息队列Kafka与RabbitMQ深度解析:把分布式消息核心讲透,吊打面试官
redis·后端
青Cheng序员石头18 小时前
龙虾运行时安全部署 | NVIDIA NemoClaw 深度研究报告
后端·aigc·nvidia