责任链模式 Go 语言实战

责任链模式(Chain of Responsibility)

责任链模式是一种行为设计模式,它允许将请求沿着处理者链进行传递,直到有一个处理者能够处理它。这个模式的主要目的是解耦请求的发送者和接收者,使得多个对象都有机会处理这个请求,而不需要明确指定哪个对象处理请求。

责任链模式的结构
  1. 处理者接口(Handler):定义一个处理请求的接口,通常包括一个处理请求的方法和一个设置下一个处理者的方法。
  2. 具体处理者(Concrete Handler):实现处理者接口的类。每个具体处理者都包含对下一个处理者的引用。如果当前处理者能够处理请求,它就会处理;否则,它会将请求传递给下一个处理者。
  3. 客户端(Client):负责创建处理者链并将请求发送到链的起始处理者。
责任链模式的适用场景
  1. 请求的处理方式和顺序未知:当程序需要使用不同方式处理不同种类的请求,且请求类型和顺序预先未知时,责任链模式非常适用。
  2. 多个处理者按顺序执行:当必须按顺序执行多个处理者时,责任链模式可以确保所有请求严格按照链上的顺序通过处理者。
  3. 动态改变处理者及其顺序:可以在运行时动态地插入和移除处理者,或者改变其顺序。
责任链模式的优点
  • 降低耦合度:请求的发送者和接收者解耦。
  • 增强灵活性:可以在运行时动态地添加、删除或重新排列处理者。
  • 责任分担:多个处理者可以分担处理请求的责任。
责任链模式的缺点
  • 请求处理不保证:如果链上的所有处理者都不能处理请求,可能会导致请求未被处理。
  • 调试困难:由于请求沿着链传递,可能会导致调试和跟踪请求处理过程变得复杂。

示例场景:请求的处理方式和顺序未知——在线客服系统

假设我们有一个在线客服系统,用户的请求需要根据不同的情况进行处理。请求可能包括以下几种类型:

  1. 技术支持:处理技术相关的问题。
  2. 销售咨询:处理销售相关的问题。
  3. 投诉处理:处理用户投诉。
  4. 一般查询:处理一般性查询。

在这个场景中,用户请求的处理方式和顺序是未知的。我们可以使用责任链模式来动态地决定请求的处理者和处理顺序。

示例代码

以下是一个使用责任链模式实现在线客服系统的 Go 代码示例:

package mainimport ("fmt"
)// Request 是一个简单的请求结构体,包含请求类型和内容。
type Request struct {Type    stringContent string
}// Handler 是处理者接口,定义了处理请求的方法和设置下一个处理者的方法。
type Handler interface {SetNext(handler Handler) HandlerHandle(request *Request) bool
}// BaseHandler 是一个基础处理者结构体,实现了 Handler 接口。
type BaseHandler struct {next Handler
}// SetNext 设置下一个处理者。
func (h *BaseHandler) SetNext(handler Handler) Handler {h.next = handlerreturn handler
}// Handle 调用下一个处理者。
func (h *BaseHandler) Handle(request *Request) bool {if h.next != nil {return h.next.Handle(request)}return true
}// TechSupportHandler 是一个具体处理者,负责处理技术支持请求。
type TechSupportHandler struct {BaseHandler
}// Handle 处理技术支持请求。
func (h *TechSupportHandler) Handle(request *Request) bool {if request.Type == "tech_support" {fmt.Println("Handling tech support request:", request.Content)return true}return h.BaseHandler.Handle(request)
}// SalesHandler 是一个具体处理者,负责处理销售咨询请求。
type SalesHandler struct {BaseHandler
}// Handle 处理销售咨询请求。
func (h *SalesHandler) Handle(request *Request) bool {if request.Type == "sales" {fmt.Println("Handling sales request:", request.Content)return true}return h.BaseHandler.Handle(request)
}// ComplaintHandler 是一个具体处理者,负责处理投诉请求。
type ComplaintHandler struct {BaseHandler
}// Handle 处理投诉请求。
func (h *ComplaintHandler) Handle(request *Request) bool {if request.Type == "complaint" {fmt.Println("Handling complaint request:", request.Content)return true}return h.BaseHandler.Handle(request)
}// GeneralQueryHandler 是一个具体处理者,负责处理一般查询请求。
type GeneralQueryHandler struct {BaseHandler
}// Handle 处理一般查询请求。
func (h *GeneralQueryHandler) Handle(request *Request) bool {if request.Type == "general_query" {fmt.Println("Handling general query request:", request.Content)return true}return h.BaseHandler.Handle(request)
}func main() {// 创建请求requests := []*Request{{Type: "tech_support", Content: "How to reset my password?"},{Type: "sales", Content: "What is the price of product X?"},{Type: "complaint", Content: "I am not satisfied with the service."},{Type: "general_query", Content: "What are your working hours?"},}// 创建处理者techSupportHandler := &TechSupportHandler{}salesHandler := &SalesHandler{}complaintHandler := &ComplaintHandler{}generalQueryHandler := &GeneralQueryHandler{}// 动态设置责任链techSupportHandler.SetNext(salesHandler).SetNext(complaintHandler).SetNext(generalQueryHandler)// 处理请求for _, request := range requests {if techSupportHandler.Handle(request) {fmt.Println("Request processed successfully.")} else {fmt.Println("Request processing failed.")}}
}

示例场景:多个处理者按顺序执行——电子商务平台的订单处理系统

在这个系统中,订单需要经过多个步骤的处理,每个步骤都由一个处理者负责。处理步骤必须按特定顺序执行,以确保订单的正确处理。

场景描述
  1. 库存检查:在处理订单之前,系统需要检查所需商品的库存是否充足。如果库存不足,订单处理将被中止。
  2. 支付处理:如果库存充足,系统将处理支付事务。如果支付失败,订单处理将被中止。
  3. 订单确认:如果支付成功,系统将确认订单并通知用户。
  4. 发货安排:最后,系统安排发货,将订单信息传递给物流部门。
示例代码

以下是一个简单的 Go 代码示例,展示了如何使用责任链模式实现上述订单处理场景:

package mainimport ("fmt"
)// Handler 是处理者接口,定义了处理请求的方法和设置下一个处理者的方法。
type Handler interface {SetNext(handler Handler) HandlerHandle(order *Order) bool
}// Order 是一个简单的订单结构体,包含订单信息。
type Order struct {ItemID    stringQuantity  intPaymentOK bool
}// BaseHandler 是一个基础处理者结构体,实现了 Handler 接口。
type BaseHandler struct {next Handler
}// SetNext 设置下一个处理者。
func (h *BaseHandler) SetNext(handler Handler) Handler {h.next = handlerreturn handler
}// Handle 调用下一个处理者。
func (h *BaseHandler) Handle(order *Order) bool {if h.next != nil {return h.next.Handle(order)}return true
}// InventoryHandler 是一个具体处理者,负责检查库存。
type InventoryHandler struct {BaseHandler
}// Handle 检查库存是否充足。
func (h *InventoryHandler) Handle(order *Order) bool {if order.Quantity > 10 { // 假设库存不足的条件fmt.Println("Insufficient inventory!")return false}fmt.Println("Inventory is sufficient.")return h.BaseHandler.Handle(order)
}// PaymentHandler 是一个具体处理者,负责处理支付。
type PaymentHandler struct {BaseHandler
}// Handle 处理支付事务。
func (h *PaymentHandler) Handle(order *Order) bool {if !order.PaymentOK {fmt.Println("Payment failed!")return false}fmt.Println("Payment processed successfully.")return h.BaseHandler.Handle(order)
}// ConfirmationHandler 是一个具体处理者,负责确认订单。
type ConfirmationHandler struct {BaseHandler
}// Handle 确认订单。
func (h *ConfirmationHandler) Handle(order *Order) bool {fmt.Println("Order confirmed.")return h.BaseHandler.Handle(order)
}// ShippingHandler 是一个具体处理者,负责安排发货。
type ShippingHandler struct {BaseHandler
}// Handle 安排发货。
func (h *ShippingHandler) Handle(order *Order) bool {fmt.Println("Shipping arranged.")return h.BaseHandler.Handle(order)
}func main() {// 创建订单order := &Order{ItemID:    "12345",Quantity:  5,PaymentOK: true,}// 创建处理者inventoryHandler := &InventoryHandler{}paymentHandler := &PaymentHandler{}confirmationHandler := &ConfirmationHandler{}shippingHandler := &ShippingHandler{}// 设置责任链inventoryHandler.SetNext(paymentHandler).SetNext(confirmationHandler).SetNext(shippingHandler)// 处理订单if inventoryHandler.Handle(order) {fmt.Println("Order processed successfully.")} else {fmt.Println("Order processing failed.")}
}

动态改变处理者及其顺序

在某些应用场景中,处理请求的逻辑可能需要在运行时动态调整。例如,在一个复杂的电子商务平台中,订单处理流程可能会根据业务需求或用户类型进行动态调整。责任链模式可以通过动态插入、移除或重新排列处理者来实现这种灵活性。

示例代码

以下是一个使用责任链模式实现动态调整处理者顺序的 Go 代码示例:

package mainimport ("fmt"
)// Handler 是处理者接口,定义了处理请求的方法和设置下一个处理者的方法。
type Handler interface {SetNext(handler Handler) HandlerHandle(order *Order) bool
}// Order 是一个简单的订单结构体,包含订单信息。
type Order struct {ItemID    stringQuantity  intPaymentOK bool
}// BaseHandler 是一个基础处理者结构体,实现了 Handler 接口。
type BaseHandler struct {next Handler
}// SetNext 设置下一个处理者。
func (h *BaseHandler) SetNext(handler Handler) Handler {h.next = handlerreturn handler
}// Handle 调用下一个处理者。
func (h *BaseHandler) Handle(order *Order) bool {if h.next != nil {return h.next.Handle(order)}return true
}// InventoryHandler 是一个具体处理者,负责检查库存。
type InventoryHandler struct {BaseHandler
}// Handle 检查库存是否充足。
func (h *InventoryHandler) Handle(order *Order) bool {if order.Quantity > 10 { // 假设库存不足的条件fmt.Println("Insufficient inventory!")return false}fmt.Println("Inventory is sufficient.")return h.BaseHandler.Handle(order)
}// PaymentHandler 是一个具体处理者,负责处理支付。
type PaymentHandler struct {BaseHandler
}// Handle 处理支付事务。
func (h *PaymentHandler) Handle(order *Order) bool {if !order.PaymentOK {fmt.Println("Payment failed!")return false}fmt.Println("Payment processed successfully.")return h.BaseHandler.Handle(order)
}// ConfirmationHandler 是一个具体处理者,负责确认订单。
type ConfirmationHandler struct {BaseHandler
}// Handle 确认订单。
func (h *ConfirmationHandler) Handle(order *Order) bool {fmt.Println("Order confirmed.")return h.BaseHandler.Handle(order)
}// ShippingHandler 是一个具体处理者,负责安排发货。
type ShippingHandler struct {BaseHandler
}// Handle 安排发货。
func (h *ShippingHandler) Handle(order *Order) bool {fmt.Println("Shipping arranged.")return h.BaseHandler.Handle(order)
}// CouponHandler 是一个具体处理者,负责验证优惠券。
type CouponHandler struct {BaseHandler
}// Handle 验证优惠券。
func (h *CouponHandler) Handle(order *Order) bool {fmt.Println("Coupon validated.")return h.BaseHandler.Handle(order)
}func main() {// 创建订单order := &Order{ItemID:    "12345",Quantity:  5,PaymentOK: true,}// 创建处理者inventoryHandler := &InventoryHandler{}paymentHandler := &PaymentHandler{}confirmationHandler := &ConfirmationHandler{}shippingHandler := &ShippingHandler{}couponHandler := &CouponHandler{}// 动态设置责任链// 例如:在促销活动中插入优惠券验证步骤inventoryHandler.SetNext(couponHandler).SetNext(paymentHandler).SetNext(confirmationHandler).SetNext(shippingHandler)// 处理订单if inventoryHandler.Handle(order) {fmt.Println("Order processed successfully.")} else {fmt.Println("Order processing failed.")}// 动态移除处理者// 例如:移除发货安排步骤inventoryHandler.SetNext(paymentHandler).SetNext(confirmationHandler)// 处理订单if inventoryHandler.Handle(order) {fmt.Println("Order processed successfully without shipping.")} else {fmt.Println("Order processing failed.")}
}

通用责任链实现

为了实现更通用的责任链模式,我们可以设计一个框架,使得责任链的构建和管理更加灵活。以下是一个更通用的责任链实现,支持通过任意数据源动态配置责任链:

package mainimport ("fmt"
)// Request 是一个简单的请求结构体,包含请求类型和内容。
type Request struct {Type    stringContent string
}// Handler 是处理者接口,定义了处理请求的方法和设置下一个处理者的方法。
type Handler interface {SetNext(handler Handler) HandlerHandle(request *Request) bool
}// BaseHandler 是一个基础处理者结构体,实现了 Handler 接口。
type BaseHandler struct {next Handler
}// SetNext 设置下一个处理者。
func (h *BaseHandler) SetNext(handler Handler) Handler {h.next = handlerreturn handler
}// Handle 调用下一个处理者。
func (h *BaseHandler) Handle(request *Request) bool {if h.next != nil {return h.next.Handle(request)}return true
}// TechSupportHandler 是一个具体处理者,负责处理技术支持请求。
type TechSupportHandler struct {BaseHandler
}// Handle 处理技术支持请求。
func (h *TechSupportHandler) Handle(request *Request) bool {if request.Type == "tech_support" {fmt.Println("Handling tech support request:", request.Content)return true}return h.BaseHandler.Handle(request)
}// SalesHandler 是一个具体处理者,负责处理销售咨询请求。
type SalesHandler struct {BaseHandler
}// Handle 处理销售咨询请求。
func (h *SalesHandler) Handle(request *Request) bool {if request.Type == "sales" {fmt.Println("Handling sales request:", request.Content)return true}return h.BaseHandler.Handle(request)
}// ComplaintHandler 是一个具体处理者,负责处理投诉请求。
type ComplaintHandler struct {BaseHandler
}// Handle 处理投诉请求。
func (h *ComplaintHandler) Handle(request *Request) bool {if request.Type == "complaint" {fmt.Println("Handling complaint request:", request.Content)return true}return h.BaseHandler.Handle(request)
}// GeneralQueryHandler 是一个具体处理者,负责处理一般查询请求。
type GeneralQueryHandler struct {BaseHandler
}// Handle 处理一般查询请求。
func (h *GeneralQueryHandler) Handle(request *Request) bool {if request.Type == "general_query" {fmt.Println("Handling general query request:", request.Content)return true}return h.BaseHandler.Handle(request)
}// HandlerFactory 是一个工厂方法,用于根据名称创建处理者实例。
func HandlerFactory(name string) Handler {switch name {case "tech_support":return &TechSupportHandler{}case "sales":return &SalesHandler{}case "complaint":return &ComplaintHandler{}case "general_query":return &GeneralQueryHandler{}default:return nil}
}// BuildChain 根据处理者名称列表构建责任链。
func BuildChain(handlerNames []string) Handler {var firstHandler Handlervar currentHandler Handlerfor _, name := range handlerNames {handler := HandlerFactory(name)if handler == nil {fmt.Println("Unknown handler:", name)continue}if firstHandler == nil {firstHandler = handlercurrentHandler = handler} else {currentHandler = currentHandler.SetNext(handler)}}return firstHandler
}func main() {// 创建请求requests := []*Request{{Type: "tech_support", Content: "How to reset my password?"},{Type: "sales", Content: "What is the price of product X?"},{Type: "complaint", Content: "I am not satisfied with the service."},{Type: "general_query", Content: "What are your working hours?"},}// 假设从某个数据源(如配置文件、数据库、环境变量)获取处理者顺序handlerNames := []string{"tech_support", "sales", "complaint", "general_query"}// 构建责任链firstHandler := BuildChain(handlerNames)// 处理请求for _, request := range requests {if firstHandler.Handle(request) {fmt.Println("Request processed successfully.")} else {fmt.Println("Request processing failed.")}}
}

代码说明

  1. Handler 接口和 BaseHandler:定义了处理者接口和基础处理者结构体。
  2. 具体处理者:实现了不同类型请求的处理者。
  3. HandlerFactory:工厂方法,根据名称创建处理者实例。
  4. BuildChain:根据处理者名称列表构建责任链。
  5. 数据源:在 main 函数中,假设从某个数据源(如配置文件、数据库、环境变量)获取处理者顺序。

通过这种设计,责任链的构建可以从外部数据源获取配置,实现动态调整而无需修改代码。你可以根据具体需求选择合适的数据源和配置管理方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/89462.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/89462.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用开源项目youlai_boot 导入到ecplise 中出现很多错误

我是使用ecplise 导入得youlai_boot 这个项目,但是导入到ecplise 中一直出现报错,然后各种maven clean 和maven install 以及update Maven 都没有效果不知道怎么办才好,怎么样解决这个问题,原来是我本地的环境中没有安装 lombok.…

06_Americanas精益管理项目_数据分析

文章目录 Americanas精益管理项目_数据分析(一)思维方法1、数据分析思维2、零售行业-万能「人货场」分析框架(二)商品分析1、品类销量分析2、销量趋势分析3、帕累托法则分析4、商品TopN分析(三)用户分析(四)场景分析Americanas精益管理项目_数据分析 数据分析与数据开…

ES6从入门到精通:类与继承

ES6 类的基本概念 ES6 引入了基于类的面向对象编程语法,通过 class 关键字定义类。类可以包含构造函数、方法和属性。 class Person {constructor(name) {this.name name;}greet() {console.log(Hello, ${this.name}!);} }const person new Person(Alice); pers…

【经验】新版Chrome中Proxy SwitchyOmega2已实效,改为ZeroOmega

1、问题描述 手欠更新了 Chrome 导致无法“上网”,原因是 Proxy SwitchyOmega2 已实效。 2、解决方法 2.1 下载 新版Chrome中Proxy SwitchyOmega2已实效,改为ZeroOmega; 想方设法去下载 ZeroOmega 的crx包,最新的为&#xff1…

在windows上设置python的环境

安装好了python,再具体说下python语言的相关环境。 #01 关于Python Python 是一个高级别的、边运行边解释的、动态类型的编程语言,以简洁的语法、强大的功能和丰富的资源库而闻名。广泛应用于 Web 开发、数据分析、人工智能、自动化脚本等多个领域。 目前 Python 语言有两…

3D 建模与点云建模:从虚拟构建到实景复刻的数字孪生双引擎

在数字化浪潮席卷全球的当下,3D 建模与点云建模如同数字世界的左膀右臂,一个以抽象化的创意构建虚拟蓝图,一个以高精度的实景数据复刻现实世界。它们不仅深刻重塑了影视娱乐、工业制造、建筑设计等传统领域,更成为数字孪生技术蓬勃…

智能检测原理和架构

大家读完觉得有帮助记得关注和点赞!!! 智能检测系统基于AI和大数据分析技术,通过主动感知、行为建模与实时响应构建动态防御体系。其核心在于将传统规则匹配升级为**多模态威胁认知**,实现对新型攻击(如AI…

2025年6月个人工作生活总结

本文为 2025年6月工作生活总结。 研发编码 某国产操作系统curl下载sftp服务器文件问题记录 场景: 某国产系统curl版本信息: # curl --version curl 7.71.1 (x86_64-koji-linux-gnu) libcurl/7.71.1 OpenSSL/1.1.1f-fips zlib/1.2.11 brotli/1.0.7 li…

Java 导出PDF 1、内容可以插入自定义表格 2、内容插入图片

Java PDF导出工具:自定义表格与图片插入 下面我将实现一个Java PDF导出工具,支持插入自定义表格和图片的功能。这个解决方案使用iText 7库,提供了一个直观的用户界面,可以预览生成的PDF内容。 import javax.swing.*; import jav…

sklearn机器学习概述及API详细使用指南

一、机器学习与sklearn简介 机器学习是人工智能的一个分支,它通过算法让计算机从数据中学习规律,并基于这些规律做出预测或决策。scikit-learn(简称sklearn)是Python中最流行的机器学习库之一,它提供了各种监督学习和…

「日拱一码」015 机器学习常用库——scikit-learn

目录 数据预处理 数据标准化(StandardScaler) 数据归一化(MinMaxScaler) 数据离散化(KBinsDiscretizer) 缺失值处理(SimpleImputer) 特征选择 基于单变量特征选择&#xff08…

网络编程学习路线

C网络编程从零基础到精通的学习路线,每一步都和你的项目实际需求紧密结合,帮助你真正做到“学以致用”。 C网络编程学习路线(结合FileHub项目) 第一阶段:网络编程基础入门 1. 计算机网络基础 理解OSI七层模型、TCP/I…

NLP:文本张量表示方法

本文目录: 一、one-hot编码二、word2vec模型(一)概念1.CBOW(Continuous bag of words)模式2.skipgram模式:3.词向量的检索获取 (二)word2vec的训练和使用1. 获取训练数据2.查看原始数据3.原始数据处理,并查…

高阶数据结构------并查集

并查集 在一些应用问题中,需要将n个不同的元素划分成一些不相交的集合。开始时,每个元素自成一个集合,然后按照一定的规律将归于同一组的元素集合合并。在此过程中要反复用到查询某一个元素归属于哪一个集合的运算。适合于描述这类问题的抽象…

OWASP Top 10 是什么?

OWASP(Open Web Application Security Project,开放Web应用安全项目)是一个致力于提高软件安全性的国际非营利组织。其发布的 ​OWASP Top 10​ 是最具影响力的Web应用安全风险清单,每3-4年更新一次,帮助开发人员、安全…

如何在IIS上部署net系统(安装iis参考上一篇)

1.对后端项目打包,我使用的时rider 2.打包前端 npm run build 3.在iis上部署 网站-添加网站 4.选择之前打包的后端文件,设置端口 5.安装对应net环境插件:主要是runtime和sdk插件以及dotnet-hosting-2.2.0-win,具体版本看自己项…

Docker可视化管理工具Portainer安装部署

1、安装Portainer 编写docker compose文件,使用docker compose文件完成Portainer的安装,首先需要在服务器上编写的名为portainer.yaml的文件,内容如下: [rootserver ~]# cat portainer.yaml services: portainer: image:…

ai之RAG本地知识库--基于OCR和文本解析器的新一代RAG引擎:RAGFlow 认识和源码剖析

目录标题 RAG本地知识库问答——基于OCR和文本解析器的新一代RAG引擎:RAGFlow 认识和源码剖析RAGflow 主要功能: 一、RAGflow 简介1.1 允许用户上传并管理自己的文档(文档类型可以是任意类型)1.2 RAGFlow的4个特色1.2.1 AI 模型的智能文档处理系统1.2.2 …

[面试] 手写题-new

function mynew(Func, ...args) {// 1.创建一个空对象const obj {}// 2.新对象隐式原型指向构造函数的显式原型obj.__proto__ Func.prototype// 3.将构建函数的this指向新对象let result Func.apply(obj, args)// 4.返回objreturn result instanceof Object ? result : obj…

设计模式精讲 Day 20:状态模式(State Pattern)

【设计模式精讲 Day 20】状态模式(State Pattern) 文章标签 设计模式, 状态模式, Java开发, 面向对象设计, 软件架构, 设计模式实战, Java应用开发 文章简述 状态模式是行为型设计模式中的重要一员,用于管理对象在不同状态下的行为变化。在…