責任鏈模式 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
英文地址,請注明出處:http://en.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應用開發 文章簡述 狀態模式是行為型設計模式中的重要一員,用于管理對象在不同狀態下的行為變化。在…