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)
}
相关推荐
2401_882727571 小时前
低代码配置式组态软件-BY组态
前端·后端·物联网·低代码·前端框架
追逐时光者2 小时前
.NET 在 Visual Studio 中的高效编程技巧集
后端·.net·visual studio
渊渟岳3 小时前
掌握设计模式--装饰模式
设计模式
大梦百万秋3 小时前
Spring Boot实战:构建一个简单的RESTful API
spring boot·后端·restful
斌斌_____3 小时前
Spring Boot 配置文件的加载顺序
java·spring boot·后端
路在脚下@3 小时前
Spring如何处理循环依赖
java·后端·spring
海绵波波1074 小时前
flask后端开发(1):第一个Flask项目
后端·python·flask
zh路西法5 小时前
【C++决策和状态管理】从状态模式,有限状态机,行为树到决策树(二):从FSM开始的2D游戏角色操控底层源码编写
c++·游戏·unity·设计模式·状态模式
小奏技术5 小时前
RocketMQ结合源码告诉你消息量大为啥不需要手动压缩消息
后端·消息队列
夏旭泽5 小时前
设计模式-备忘录模式
设计模式·备忘录模式