設計模式筆記_行為型_責任鏈模式

1. 責任鏈模式介紹

責任鏈模式(Chain of Responsibility)是一種行為設計模式,它允許將多個處理器(處理對象)連接成一條鏈,并沿著這條鏈傳遞請求,直到有一個處理器處理它為止。職責鏈模式的主要目的是避免請求的發送者與多個請求處理者之間的耦合。

類比場景:想象一下,客戶服務中心有多個層級的客服人員:初級客服、高級客服和經理。客戶的問題會從初級客服開始,逐級向上轉發,直到有一個客服能夠解決問題。

組成結構:職責鏈模式主要包含以下幾個部分:

  1. 抽象處理者(Handler):定義一個處理請求的接口,并包含一個指向下一個處理者的引用。
  2. 具體處理者(ConcreteHandler):實現處理請求的具體邏輯,并決定是否將請求傳遞給下一個處理者。
  3. 處理器鏈(HandlerChain):?在職責鏈模式的實現中,使用HandlerChain不是必須的,但是一種常見的做法。HandlerChain?的使用主要是為了簡化鏈的管理,使得鏈的創建和維護更加便捷和集中。
  4. 客戶端(Client):負責創建處理鏈,并向鏈中的第一個處理者發送請求。

優缺點分析:

  • 優點
    • 降低耦合:請求發送者和接收者之間的耦合度降低,靈活地新增和修改處理者。
    • 動態組合:可以方便地改變鏈內的成員或調動它們的次序。
  • 缺點
    • 不保證請求被處理:如果鏈的末端沒有處理請求,可能會導致請求不被處理。這個場景可以通過責任鏈的變體實現,讓請求被所有處理器都處理。
    • 性能問題:鏈過長可能導致性能問題,因為請求需要經過多個處理者。

適用場景:

  • 需要動態地指定請求的處理者。
  • 有多個對象可以處理某個請求,但具體處理者不確定。
  • 希望請求的發送者和接收者解耦。

2. 代碼演示

責任鏈有鏈表列表兩種實現方式,這里分別演示。演示場景圍繞“初級客服、高級客服和經理處理客訴”展開。

2.1 鏈表實現

抽象處理者(Handler):鏈式實現方式中,抽象處理類是一個抽象類,里面定義了處理請求的接口(這里是doHandle接口),并包含指向下一個處理者的引用(這里對應nextHandler屬性)。通常還會將調用下個處理器的通用邏輯提取出來(對應handleRequest方法),這樣具體處理器類只需要實現自己的業務邏輯就可以了。

// 抽象處理者
public abstract class CustomerServiceHandler {//下一個處理器的對象protected CustomerServiceHandler nextHandler;public void setNextHandler(CustomerServiceHandler nextHandler) {this.nextHandler = nextHandler;}//調用下個處理器的邏輯,原本放在具體處理器中;屬于通用邏輯,這里利用模版模式提取到父類public void handleRequest(String request) {boolean handled = doHandle(request);//gof定義:若當前處理器不能處理,則需要向下個處理器傳遞; 否則結束if (!handled && nextHandler != null) {nextHandler.handleRequest(request);}}//抽象處理邏輯:具體實現放在各handler自己實現的  doHandle() 函數里public abstract boolean doHandle(String request);}

具體處理者(ConcreteHandler):

//具體處理者 - 初級客服
public class JuniorCustomerService extends CustomerServiceHandler {@Overridepublic boolean doHandle(String request) {if (request.equals("basic")) {System.out.println("junior customer service handle");return true;}return false;}
}// 具體處理者 - 高級客服
public class SeniorCustomerService extends CustomerServiceHandler {@Overridepublic boolean doHandle(String request) {if (request.equals("advanced")) {System.out.println("senior customer service handle");return true;}return false;}
}// 具體處理者 - 經理
public class Manager extends CustomerServiceHandler {@Overridepublic boolean doHandle(String request) {if (request.equals("complex")) {System.out.println("manager customer service handle");return true;}return false;}
}

處理器鏈(HandlerChain):HandlerChain不是必須的,在某些情況下,直接在客戶端代碼中構建職責鏈是足夠的,尤其是鏈簡單且變化不頻繁的時候。然而,在處理復雜鏈或需要動態調整鏈的場景下,引入?HandlerChain?可以提高代碼的清晰度和靈活性。通過HandlerChain集中管理handlers,負責鏈中處理者的添加、移除和遍歷,簡化鏈的管理。

public class CustomerServiceHandlerChain {private CustomerServiceHandler firstHandler;private CustomerServiceHandler lastHandler;//給鏈表中添加處理器public void addHandler(CustomerServiceHandler handler) {if (firstHandler == null) {//鏈表頭為null,放在鏈表頭firstHandler = handler;lastHandler = handler;} else {//否則放在鏈表尾lastHandler.setNextHandler(handler);lastHandler = handler;}}//執行鏈表中的處理器:從第一個處理器開始執行public void handleRequest(String request) {if (null != firstHandler) {firstHandler.handleRequest(request);}}
}

客戶端代碼:

public class CustomerServiceChainDemo {public static void main(String[] args) {CustomerServiceHandlerChain handlerChain = new CustomerServiceHandlerChain();handlerChain.addHandler(new JuniorCustomerService());handlerChain.addHandler(new SeniorCustomerService());handlerChain.addHandler(new Manager());// 測試不同請求//handlerChain.handleRequest("basic");handlerChain.handleRequest("advanced");}
}

對應的類圖:

2.2?列表實現

列表實現方式更加簡單,與鏈表實現的差異點:

  • 抽象處理者(handler)改用interface (無需存儲對下一個處理者的引用)
  • HandlerChain類中用列表而非鏈表來保存所有的處理器
  • 在HandlerChain中,依次調用每個handler(鏈表對nextHandler的調用放在抽象處理者類中)

抽象處理者(Handler):列表實現方式中,抽象處理者是一個接口,定義處理請求的方法。

//抽象處理者
public interface CustomerServiceHandler {boolean handlerRequest(String request);
}

具體處理者(ConcreteHandler):

//具體處理者 - 初級客服
public class JuniorCustomerService implements CustomerServiceHandler {@Overridepublic boolean handlerRequest(String request) {if (request.equals("basic")) {System.out.println("junior customer service handle");return true;}return false;}
}//具體處理者 - 高級客服
public class SeniorCustomerService implements CustomerServiceHandler {@Overridepublic boolean handlerRequest(String request) {if (request.equals("advanced")) {System.out.println("senior customer service handle");return true;}return false;}
}//具體處理者 - 經理
public class Manager implements CustomerServiceHandler {@Overridepublic boolean handlerRequest(String request) {if (request.equals("complex")) {System.out.println("manager customer service handle");return true;}return false;}
}

處理器鏈(HandlerChain):HandlerChain類中用列表而非鏈表來保存所有的處理器,并在HandlerChain的handle()函數中,依次調用每個處理器的handle()函數。

public class CustomerServiceHandlerChain {private List<CustomerServiceHandler> handlerList = new ArrayList<>();public void addHandler(CustomerServiceHandler handler) {handlerList.add(handler);}public void handleRequest(String request) {for (CustomerServiceHandler handler : handlerList) {//gof定義: 若當前處理器不能處理,則向下一個處理器傳遞; 否則結束Boolean handledResult = handler.handlerRequest(request);if (handledResult) {break;}}}
}

客戶端代碼:

public class CustomerServiceChainDemo {public static void main(String[] args) {CustomerServiceHandlerChain handlerChain = new CustomerServiceHandlerChain();handlerChain.addHandler(new JuniorCustomerService());handlerChain.addHandler(new SeniorCustomerService());handlerChain.addHandler(new Manager());// 測試不同請求handlerChain.handleRequest("basic");}
}

對應的類圖:

2.3 變體:所有handler都處理一遍

上述實現是按照gof定義:如果處理器鏈上的某個處理器能夠處理這個請求,那就不會繼續往下傳遞請求,整個流程就會結束

職責鏈模式還有一種變體,那就是請求會被所有的處理器都處理一遍,不存在中途終止的情況。還是使用上述客服場景,假設用戶需要退款,需要 初級/高級/經理 三級客服簽字確認。

列表實現的代碼如下:

//抽象處理者
public interface CustomerServiceHandler {void handlerRequest(String request);
}
//具體處理者 - 初級客服
public class JuniorCustomerService implements CustomerServiceHandler {@Overridepublic void handlerRequest(String request) {//doSomething ...System.out.println("junior customer service handle");}
}//具體處理者 - 高級客服
public class SeniorCustomerService implements CustomerServiceHandler {@Overridepublic void handlerRequest(String request) {//doSomething ...System.out.println("senior customer service handle");}
}//具體處理者 - 經理
public class Manager implements CustomerServiceHandler {@Overridepublic void handlerRequest(String request) {//doSomething ...System.out.println("manager customer service handle");}
}
//處理器鏈
public class CustomerServiceHandlerChain {private List<CustomerServiceHandler> handlerList = new ArrayList<>();public void addHandler(CustomerServiceHandler handler) {handlerList.add(handler);}public void handleRequest(String request) {for (CustomerServiceHandler handler : handlerList) {//變體類型: 不關注 handled值,請求會被所有的處理器都處理一遍,不存在中途終止的情況handler.handlerRequest(request);}}
}
//客戶端代碼
public class CustomerServiceChainDemo {public static void main(String[] args) {CustomerServiceHandlerChain handlerChain = new CustomerServiceHandlerChain();handlerChain.addHandler(new JuniorCustomerService());handlerChain.addHandler(new SeniorCustomerService());handlerChain.addHandler(new Manager());//發起退款handlerChain.handleRequest("退款100元");}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/93117.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/93117.shtml
英文地址,請注明出處:http://en.pswp.cn/web/93117.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

pygame的幀處理中,涉及鍵盤的有`pg.event.get()`與`pg.key.get_pressed()` ,二者有什么區別與聯系?

一、pg.event.get() 返回的是一組事件 pg.event.get() 返回的是一組事件&#xff08;一個包含多個事件對象的列表&#xff09;。這是因為在游戲的“一幀”時間內&#xff08;通常1/60秒左右&#xff09;&#xff0c;用戶可能會觸發多個事件&#xff08;比如同時按下多個鍵、快速…

TF - IDF算法面試與工作常見問題全解析

在自然語言處理領域&#xff0c;TF - IDF算法是一個基礎且重要的概念。無論是在求職面試還是在實際工作中&#xff0c;都經常會遇到與TF - IDF相關的問題。以下是一些常見的問題及其詳細解答&#xff1a; 一、基本概念類問題 1. 什么是TF - IDF算法&#xff1f; TF - IDF&#…

Transformer網絡結構解析

博主會經常分享自己在人工智能階段的學習筆記&#xff0c;歡迎大家訪問我滴個人博客&#xff01;&#xff08;都不白來&#xff01;&#xff09; 小牛壯士 - 個人博客https://kukudelin.top/ 前言 Transformer 廣泛應用于自然語言處理&#xff08;如機器翻譯、文本生成&…

gateway進行接口日志打印

打印需求&#xff1a;對所有的接口打印&#xff1a;請求方式&#xff0c;請求路徑&#xff0c;請求參數&#xff0c;用戶id&#xff0c;訪問IP&#xff0c;訪問時間對增刪改操作的接口打印&#xff1a;接口響應打印方案&#xff1a;給GET設置一個白名單&#xff08;因為get請求…

MATLAB實現圖像增強(直方圖均衡化)

直方圖均衡化是一種常用的圖像增強技術&#xff0c;它通過重新分布圖像的像素強度值來增強圖像的對比度。以下是MATLAB中實現直方圖均衡化的詳細方法。%% 直方圖均衡變換 clc;close all;clear all;warning off;%清除變量 rand(seed, 100); randn(seed, 100); format long g;%% …

java15學習筆記-密封類

360:Sealed Classes (Preview) 封閉類&#xff08;預覽&#xff09; 總結 使用密封類和接口增強Java編程語言。密封類和接口限制了哪些其他類或接口可以擴展或實現它們。這是JDK 15中的預覽語言功能。 目標 允許類或接口的作者控制負責實現它的代碼。 提供一種比訪問…

西門子PLC通過穩聯技術EtherCAT轉Profinet網關連接baumuller伺服器的配置案例

西門子PLC用穩聯技術的EtherCAT轉Profinet網關&#xff0c;連上baumuller伺服器的配置例子本案例實現西門子S71200 PLC通過EtherCAT轉Profinet網關對baumuller&#xff08;Baumller&#xff09;伺服器的實時控制&#xff0c;適用于高精度運動控制場景&#xff08;如精密機床、自…

Ansible 詳細筆記

Ansible 詳細筆記 一、Ansible 基礎概述 1.1 定義與定位 Ansible 是由 Red Hat 主導開發的開源自動化運維工具&#xff0c;基于 Python 語言實現&#xff0c;專注于簡化 IT 基礎設施的配置管理、應用部署、任務編排等操作。它采用無代理架構&#xff0c;通過 SSH 協議與被控節點…

【Java 后端】Spring Boot 集成 JPA 全攻略

Spring Boot 集成 JPA 全攻略 一、前言 在 Java Web 開發中&#xff0c;數據庫訪問是繞不開的話題。 傳統方式使用 JDBC 編寫 SQL&#xff0c;維護困難、可讀性差。后來有了 MyBatis 這種半自動 ORM 框架&#xff0c;再到 JPA&#xff08;Java Persistence API&#xff09;這…

pytorch學習筆記-加載現有的網絡模型(VGG16)、增加/修改其中的網絡層(修改為10分類)

寫在前面&#xff1a;有些地方和視頻里不一樣的是因為官方文檔更新了&#xff0c;一些參數用法不一樣也很正常&#xff0c;包括我現在的也是我這個時間節點最新的&#xff0c;誰知道過段時間會不會更新呢 建議大家不要一味看視頻/博客&#xff0c;多看看官方文檔才是正道&#…

RocketMQ 4.9.3源碼解讀-NameServer組件啟動流程分析

作者源碼閱讀筆記主要采用金山云文檔記錄的,所有的交互圖和代碼閱讀筆記都是記錄在云文檔里面,本平臺的文檔編輯實在不方便,會導致我梳理的交互圖和文檔失去原來的格式,所以整理在文檔里面,供大家閱讀交流 【金山文檔 | WPS云文檔】 namesrv 啟動流程 相關重要類介紹說明…

《嵌入式 C 語言編碼規范與工程實踐個人筆記》參考華為C語言規范標準

《嵌入式 C 語言編碼規范與工程實踐個人筆記》參考華為C語言規范標準 前言 在電子系統開發領域&#xff0c;C 語言作為底層開發的核心語言&#xff0c;其代碼質量直接關系到系統的穩定性、可維護性和擴展性。良好的編碼規范不僅是團隊協作的基礎&#xff0c;更是降低生命周期成…

純半精度模型和全精度模型的耗時分別為248微秒和1400微秒。混合精度模型371微秒比原始模型快大約四倍!

不過有一點需要注意:在上下文管理器內部生成的任何輸出,必然會采用該上下文管理器的數據類型。因此,之后我們必須將這些輸出轉換回FP32(例如,使用float()函數)。 with torch.autocast(device_type="cuda", dtype=torch.float16): res16 = mixed32(torch.randn…

一款開源的遠程桌面軟件,旨在為用戶提供流暢的游戲體驗,支持 2K 分辨率、60 FPS,延遲僅為 40ms。

軟件介紹 CloudPlayPlus&#xff08;云玩加&#xff09;是一款令人驚艷的開源遠程桌面、串流軟件&#xff0c;云玩加由個人開發者開發者&#xff0c;具有四大特征&#xff1a;開源、免費、低延遲、安全。 軟件使用 客戶端支持多個平臺&#xff0c;包括 Windows、Mac OS、安卓…

MySql——binlog和redolog的區別

目錄一、binlog和redolog的區別一、binlog和redolog的區別 binlog和redolog都是存儲修改的新數據&#xff0c;是否保留binlog和redolog中的一個即可。 binlog屬于整個mysql&#xff0c;是所有引擎共用的&#xff0c;不是只屬于innoDB引擎。而redolog屬于InnoDB存儲引擎。binlo…

軟件著作權產生與登記關鍵點

知識講解一、 軟件著作權的核心特征與權利內容自動產生原則&#xff1a; 這是軟件著作權最核心、最重要的特征。產生時間&#xff1a; 軟件著作權自軟件開發完成之日起自動產生。法律依據&#xff1a; 《中華人民共和國著作權法》第二條及《計算機軟件保護條例》第五條明確規定…

什么是主成分分析(PCA)和數據降維

主成分分析&#xff08;PCA&#xff09;和數據降維是機器學習和統計學中處理高維數據的核心工具。下面用清晰的結構解釋其概念、原理和應用&#xff1a; 一、數據降維&#xff08;Dimensionality Reduction&#xff09; 1. 是什么&#xff1f; 目標&#xff1a;將高維數據&…

圖論(4)單源賦權最短路徑算法實現(BFS實現)

目錄 1. 什么是賦權最短路徑 2. 賦權最短路徑中的關鍵概念 3. Dijkstra 算法的基本思想 4. Dijkstra 算法實現&#xff08;Java&#xff09; 1. 什么是賦權最短路徑 在圖論中&#xff0c;最短路徑問題是指在圖中尋找兩點之間路徑總權重最小的路徑問題。如果圖的每條邊都帶…

【Lua】題目小練9

題目&#xff1a;實現一個簡單的“銀行賬戶”類要求&#xff1a;使用 元表 模擬面向對象。支持以下功能&#xff1a;Account:new(owner, balance) 創建賬戶&#xff08;初始余額可選&#xff0c;默認為 0&#xff09;。deposit(amount) 存款&#xff08;不能為負數&#xff09;…

【二分圖】染色問題

核心思想&#xff1a;為每一個未染色的&#xff0c;對它自己和它的鄰居進行染色&#xff0c;看是否會出現沖突時間復雜度O&#xff08;nm&#xff09;#include<bits/stdc.h> using namespace std; using lllong long; const int N200010; int n,m; vector<int>edge…