Java設計模式->責任鏈模式的介紹

目錄

1、責任鏈模式概念

1.1、定義介紹

1.2、流程圖

1.3、優缺點

2、實現

3、應用場景

3.1、Springmvc流程

3.2、mybatis的執行流程

3.3、Spring的過濾器和攔截器

3.4、sentinel限流熔斷

3.5、aop的加載和使用

4、舉例


前言

???????是一種?行為型設計模式,它通過將請求沿著一條處理鏈傳遞,直到某個對象處理它為止。這種模式的核心思想是?解耦請求的發送者和接收者,使多個對象都有機會處理請求,避免請求發送者與具體處理者之間的緊耦合。

????????核心思想是將請求的處理職責沿著對象鏈傳遞,而不明確指定具體哪個對象處理。

如下圖所示:

這種模式特別適用于需要多級處理的場景,例如工作流管理系統、審批流程、過濾器鏈等。

如下圖所示:


1、責任鏈模式概念

????????主要目的是解耦請求發送者接收者,使得多個對象都有機會處理請求

1.1、定義介紹

????????職責鏈模式是一種行為型設計模式,它允許將請求沿著一個處理鏈傳遞,直到鏈中的某個對象處理它。

????????將鏈中的每一個結點看做是一個對象,每個結點處理請求均不同,且內部自動維護一個下一個結點對象。當請求從鏈條的首端出發時,會沿著鏈的路徑依次傳遞給每一個結點的對象,直到有對象處理這個請求為止。

????????每個結點會處理一件事情,如果結點間出現異常,那么鏈路就會中斷。

1.2、流程圖

如下圖所示:

1.3、優缺點


1、優點:

降低耦合度:請求發送者與處理者解耦,發送者不需要知道具體哪個處理者會處理請求。
動態組合:可以靈活地修改責任鏈的結構,增加或減少處理器。
職責分離:將請求處理的各個步驟分散到不同的處理者中,符合單一職責原則。

2、缺點:

可能無處理結果:如果鏈上的所有處理者都不能處理該請求,那么該請求將被丟棄。
性能問題:責任鏈過長可能會影響系統性能,因為請求會依次傳遞給鏈上的每一個處理者。


2、實現

????????在Java中,職責鏈模式通常通過定義一個抽象處理器類來實現,該類包含處理請求的方法以及持有下一個處理器的引用。

如下圖所示:

代碼示例:

abstract class Handler {protected Handler nextHandler;public void setNextHandler(Handler nextHandler) {this.nextHandler = nextHandler;}public abstract void handleRequest(Request request);
}

????????具體的處理器類繼承自這個抽象類,并根據自己的能力決定是否處理請求或將其傳遞給下一個處理器。

代碼示例:

class ConcreteHandler1 extends Handler {@Overridepublic void handleRequest(Request request) {if (request.getLevel() == 1) {System.out.println("ConcreteHandler1 handled the request.");} else if (nextHandler != null) {nextHandler.handleRequest(request);}}
}class ConcreteHandler2 extends Handler {@Overridepublic void handleRequest(Request request) {if (request.getLevel() == 2) {System.out.println("ConcreteHandler2 handled the request.");} else if (nextHandler != null) {nextHandler.handleRequest(request);}}
}

測試:

class Request {private int level;public Request(int level) {this.level = level;}public int getLevel() {return level;}
}public class ChainOfResponsibilityPatternExample {public static void main(String[] args) {Handler handler1 = new ConcreteHandler1();Handler handler2 = new ConcreteHandler2();handler1.setNextHandler(handler2);Request request1 = new Request(1);Request request2 = new Request(2);handler1.handleRequest(request1);handler1.handleRequest(request2);}
}?

3、應用場景

????????責任鏈模式適用于需要將請求的處理邏輯分散到多個對象中的場景。

????????例如,在Java的Servlet中,當一個HTTP請求到達服務器時,可能需要經過多個Filter的處理,這種場景就可以使用職責鏈模式來實現。

????????此外,職責鏈模式還可以用于實現工作流管理系統審批流程等需要多級處理的場景。

????????在Spring MVC中,HandlerInterceptor接口允許開發者在請求處理的不同階段插入自定義邏輯。

3.1、Springmvc流程

????????這個springMvc的執行流程來說,全部流程就組成了一個鏈條。每一個步驟就是一個結點,每個結點都會有對應的處理方法,每個結點處理完成之后,就會進入下一個結點。

????????一旦某個結點出現異常,那么當前的鏈路就會停止,當前請求中斷。

3.2、mybatis的執行流程


????????mybatis的執行流程也是通過這個責任鏈模式,首先會創建這個SqlSessionFactory,然后通過這個工廠創建一個SqlSession,這個SqlSession只是一個門面模式,會通過Executer執行增刪改查的操作,然后一個Handler用于設置參數,一個Handler用于返回結果集,最后通過這個StatementHandler將執行結果獲取。

????????里面的整個步驟就相當于形成了一個鏈條,執行完當前結點就會進入下一個結點,如果出現異常,鏈條終止往下執行。

3.3、Spring的過濾器和攔截器

Spring里面的這個過濾器鏈路的調用,以及攔截器的鏈路調用,也是采用這種責任鏈模式。

3.4、sentinel限流熔斷

????????sentinel里面的每一個規則對應一個槽點,如流控規則,授權規則,熔斷規則,熱點規則,系統規則等。

????????里面也是利用這個責任鏈模式,每個插槽對應一個規則,每個規則處理一個事件。如果出現異常,那么就會進行對應的限流降級。

3.5、aop的加載和使用


????????aop依賴與ioc,在生產bean并進行實例化之前,先通過bean的第一個后置處理器找到所有在類上面加@AspectJ這個注解的所有類,并在這個類的里面找到所有的befeore,after等注解的方法,每一個before,after等都會生成一個對應的advisor,每個advisor包括advise和pointcut,advise主要是用來作為一個增強器的使用,pointcut是為了進行匹配,匹配成功才進行最終的動態代理的生成。

????????最后獲取到所有的advisors,由于可能有大量的advisor,因此在bean的最后一個后置處理器才對這些所有的advisor進行處理,即在bean進行初始化之后才進行處理。

????????最后會去循環遍歷這些advisors,通過advisors里面封裝的pointcut和生成的advisor進行比較,如果匹配成功,則說明bean需要創建動態代理。主要是通過責任鏈的方式實現。


4、舉例


????????假設有一個學校有一個采購審批的需要,采購項目需要給領導審批,不同金錢范圍,對應的審批領導的等級不同,如下:

1、金額小于5000,由教學主任審批

2、金額小于等于5000,由院長審批

3、金額小于等于30000,由副校長任審批

4、金額大于30000,由校長審批

流程圖如下:

1、首先定義一個實體類ApproverRequest

/***/
public class ApproverRequest {private int type = 0; //請求類型private float price = 0.0f; //請求金額private int id = 0;//構造器public ApproverRequest(int type, float price, int id) {this.type = type;this.price = price;this.id = id;}public int getType() { return type; }public float getPrice() { return price; }public int getId() { return id; }
}

2、定義一個抽象類,用于定義全局,作為子類的規范。

鏈條中所有的結點都需要繼承子類,實現子類里面的抽象方法。

/*** 定義全局*/
public abstract class Approver {//下一個調用者Approver next ;//需要傳入的名字String name ;public Approver(String name){this.name = name;}//設置下一個調用者public void setNext(Approver next) {this.next = next;}public abstract void processApprover(ApproveRequest approveRequest);
}

3、然后開始寫一個鏈條中的第一個結點,由教學主任負責審批。

如果金額太大,教學主任審批不了,那么就由這個院長審批。

/***/
public class DepartmentApprover extends Approver {public DepartmentApprover(String name){super(name);}@Overridepublic void processApprover(ApproverRequest approveRequest) {if(approveRequest.getPrice() <= 5000) {System.out.println(" 請求編號 id= " + approveRequest.getId() + " 被 " + this.name + " 處理");}else {next.processApprover(approveRequest);}}}

4、然后開始寫一個鏈條中的第二個結點,由院長負責審批。

如果金額太大,院長審批不了,那么就由這個副校長審批

/***/
public class CollegeApprover extends Approver{public CollegeApprover(String name) {super(name); }@Overridepublic void processApprover(ApproverRequest approveRequest) {if(approveRequest.getPrice() > 5000 && approveRequest.getPrice() <= 10000) {System.out.println(" 請求編號 id= " + approveRequest.getId() + " 被 " + this.name + " 處理");}else {next.processApprover(approveRequest);}}
}

5、然后開始寫一個鏈條中的第三個結點,由副長負責審批。

如果金額太大副校長審批不了,那么就由這個校長審批

/***/
public class ViceSchoolMasterApprover extends Approver{public ViceSchoolMasterApprover(String name) {super(name); }@Overridepublic void processApprover(ApproverRequest approveRequest) {if(approveRequest.getPrice() > 10000 && approveRequest.getPrice() <= 30000) {System.out.println(" 請求編號 id= " + approveRequest.getId() + " 被 " + this.name + " 處理");}else {next.processApprover(approveRequest);}}
}

6、然后開始寫最后一個結點,由校長審批。

/***/
public class SchoolMasterApprover extends Approver{public SchoolMasterApprover(String name) {super(name); }@Overridepublic void processApprover(ApproverRequest approveRequest) {if(approveRequest.getPrice() > 30000) {System.out.println(" 請求編號 id= " + approveRequest.getId() + " 被 " + this.name + " 處理");}else {next.processApprover(approveRequest);}}
}

7、編寫一個測試類

/***/
public class Main {public static void main(String[] args) {//創建一個請求ApproverRequest approveRequest = new ApproverRequest(1, 29000, 1);//創建相關的審批人DepartmentApprover departmentApprover = new DepartmentApprover("張主任");CollegeApprover collegeApprover = new CollegeApprover("李院長");ViceSchoolMasterApprover viceSchoolMasterApprover = new ViceSchoolMasterApprover("王副校");SchoolMasterApprover schoolMasterApprover = new SchoolMasterApprover("佟校長");//需要將各個審批級別的下一個設置好departmentApprover.setNext(collegeApprover);collegeApprover.setNext(viceSchoolMasterApprover);viceSchoolMasterApprover.setNext(schoolMasterApprover);//單向責任鏈這里可以不加schoolMasterApprover.setNext(departmentApprover);departmentApprover.processApprover(approveRequest);viceSchoolMasterApprover.processApprover(approveRequest);}
}

總結

????????責任鏈模式通過將請求傳遞給鏈上的下一個處理者,解耦了請求發送者接收者,并且可以根據需要動態組合責任鏈的結構,使得請求處理更加靈活和可擴展


參考文章:

1、Java設計模式之責任鏈模式_java責任鏈-CSDN博客https://blog.csdn.net/qq_27656927/article/details/141589649?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522ca442c1bb491a8a574936eb9ae4c884d%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=ca442c1bb491a8a574936eb9ae4c884d&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-2-141589649-null-null.142^v102^pc_search_result_base1&utm_term=java%E4%B8%AD%E7%9A%84%E8%B4%A3%E4%BB%BB%E9%93%BE%E6%A8%A1%E5%BC%8F&spm=1018.2226.3001.4187

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

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

相關文章

【Bluedroid】藍牙啟動之 btm_acl_device_down 流程源碼解析

本文詳細分析Android藍牙協議棧在設備故障時的處理流程。當藍牙設備發生硬件故障或系統異常時,協議棧通過btm_acl_device_down觸發多層次的資源清理和狀態重置,包括ACL連接終止、L2CAP通道釋放、SCO連接清理、BLE拓撲更新、設備數據庫重置等關鍵操作,確保系統安全恢復。 一、…

隨記:WebMvcConfigurationSupport 和WebMvcConfigurer 的區別

WebMvcConfigurationSupport &#xff08;抽象類&#xff09; 他是一個完整的 MVC 配置基類&#xff0c;他會禁用所有自動配置。默認靜態資源映射也沒有了。默認消息轉換器&#xff08;json、xml&#xff09;也沒有了。錯誤處理頁默認的error也沒有了。 WebMvcConfigurer &am…

npm run dev報錯

1. 引言 1.1 什么是npm run dev npm run dev 是一個在 Node.js 項目中常用的命令&#xff0c;它允許開發者運行一個預定義的腳本&#xff0c;通常用于啟動開發服務器或者執行開發環境的構建任務。這個命令是通過 package.json 文件中的 scripts 部分定義的&#xff0c;例如&…

Kotlin環境搭建與基礎語法入門

目標&#xff1a;完成開發環境配置&#xff0c;編寫第一個Kotlin程序&#xff0c;理解變量、數據類型和基本輸出。 1. 環境搭建 步驟1&#xff1a;安裝JDK 下載并安裝 JDK 17&#xff08;Kotlin兼容性最佳版本&#xff09;。 配置環境變量 JAVA_HOME&#xff0c;并在終端驗證…

CLion開發Qt桌面程序_git的簡單使用_小團體

OS&#xff1a;Windows Qt&#xff1a;6.8.1&#xff08;6.x&#xff09; Eg&#xff1a;學生信息管理系統 前言 Qt Creator編寫代碼不是太方便&#xff0c;使用CLion編寫代碼或許是個不錯的主意&#xff0c;CLion在此處主要是用于后端和測試的開發&#xff0c;界面方面還是…

C語言專題:8.函數指針(Function Pointer)

? 在 C 語言中&#xff0c;函數也是一種“對象”&#xff0c;它在內存中有地址。因此可以定義指向函數的指針&#xff0c;用于動態調用、回調處理、構建函數表等。 掌握函數指針是理解 C 語言“底層抽象”與“模塊化編程”的關鍵。 一、函數指針的基本概念 ? 函數指針是一個變…

快速傅里葉變換(FFT)是什么?

快速傅里葉變換(FFT)是什么&#xff1f; 快速傅里葉變換&#xff08;FFT&#xff09; 本質上是一種極其高效的算法&#xff0c;用來計算**離散傅里葉變換&#xff08;DFT&#xff09;**及其逆變換。它是數字信號處理、科學計算和工程應用中最重要的算法之一。 要理解 FFT&…

EEG分類 - Theta 頻帶 power

在EEG&#xff08;腦電圖&#xff09;信號處理的背景下&#xff0c;theta波段功率&#xff08;Theta Band Power&#xff09;是一個重要的特征&#xff0c;廣泛應用于認知、神經科學和臨床監測等領域。接下來&#xff0c;我將詳細介紹theta波段功率的定義、特性、計算方法以及在…

蒼穹外賣day3--公共字段填充+新增菜品

1.公共字段填充 1.1 問題分析 在新增員工或者新增菜品分類時需要設置創建時間、創建人、修改時間、修改人等字段&#xff0c;在編輯員工或者編輯菜品分類時需要設置修改時間、修改人等字段。這些字段屬于公共字段&#xff0c;也就是也就是在我們的系統中很多表中都會有這些字段…

每次選擇都是成本

概述 我們每個人都在做選擇&#xff0c;而且無時無刻不在做選擇。 有的人有的選&#xff0c;而有的人卻沒得選。 因此從側面來說&#xff0c;有的選反而更是一種幸福。 我們學習的目的就是為了讓我們自己在未來能有更好地選擇&#xff0c;也可以底氣十足地選擇不去做什么&a…

AI in CSR Writing: Revolutionizing Clinical Trial Reports

一、AI在CSR撰寫中的實際應用 1.1 自動化數據整合與報告生成 1.1.1 數據提取與匯總 AI自動從EDC、實驗室系統、安全數據庫提取數據,生成統計圖表和表格,如人口統計學、療效終點、安全性事件表,減少人工操作。 1.1.2 動態報告生成 基于預設模板,AI自動填充數據結果,如自動…

《Java反射到底該不該用?性能、靈活性與可維護性三者博弈》

大家好呀&#xff01;今天我們要聊一個Java中超級強大但也需要謹慎使用的特性——反射機制(Reflection) &#x1f3ad;。我會用最通俗易懂的方式&#xff0c;帶大家徹底搞懂這個"程序界的魔術師"&#xff01; 一、什么是Java反射&#xff1f;&#x1f914; 想象一下…

從Java API調用者到架構思考:我的Elasticsearch認知升級之路

前言&#xff1a;我的Elasticsearch學習歷程 作為一名Java開發者&#xff0c;記得第一次使用ES的Java High Level REST Client時&#xff0c;我被它強大的搜索能力所震撼&#xff0c;但也為復雜的集群調優所困擾。經過多個項目的實戰積累和系統性學習&#xff0c;我終于建立了對…

高云GW5AT-LV60 FPGA圖像處理板

GW5AT-LV60開發板體積小巧&#xff0c;長100mm寬為61.8mm&#xff0c;還沒有一部Ipone SE2體積大&#xff0c;該板卡采用了核心板和載板分離的形式&#xff0c;核心板的形式可方便開發者在項目中根據實際需求來開發自己的載板&#xff0c;只需要為核心板提供5V的電源就能滿足基…

[XILINX]ZYNQ7010_7020_軟件LVDS設計

若該文為原創文章&#xff0c;未經允許不得轉載風釋雪QQ:627833006WX:Cheng18375816918CSDN博客: 風釋雪FPGA知乎&#xff1a;風釋雪FPGA 1.版本說明 日期作者版本說明2024xxxx風釋雪初始版本 2.概述 ZYNQ 7010/7020 HR/HP Bank LVDS Rx/TX&#xff1b; 3.目標 ZYNQ 7010 LVD…

桌面小屏幕實戰課程:DesktopScreen 11 SPI 水墨屏

飛書文檔https://x509p6c8to.feishu.cn/docx/doxcnlzpIgj3gosCZufBTCZxlMb SPI說明 SPI是串行外設接口&#xff08;Serial Peripheral Interface&#xff09;的縮寫&#xff0c;是一種高速的&#xff0c;全雙工&#xff0c;同步的通信總線&#xff0c;并且在芯片的管腳上占用…

SpringCloud Gateway 組件的使用

作者&#xff1a;小凱 沉淀、分享、成長&#xff0c;讓自己和他人都能有所收獲&#xff01; 我發現了一個很有意思的縮寫單詞 gw、wg&#xff0c;都是網關的意思。因為 gw gateway、wg wangguan&#xff0c;所以在各個系統開發中&#xff0c;既有 gw 也有 wg 的存在。而網關…

隨機地址生成器 - Cloudflare Workers

分享一個完全開源免費部署在 Cloudflare Workers 上的隨機地址生成器&#xff0c;支持全球 24 個國家/地區。 &#x1f517; 工具地址: https://address.chat-tempmail.com ? 特性 &#x1f30d; 支持生成 24 個國家/地區的地址&#x1f4f1; 響應式設計&#xff0c;完美支持…

CNN不是一個模型?

CNN不是一個模型&#xff1f; 結論&#xff1a; CNN 是模型架構而非具體模型&#xff0c;其定位類似深度學習領域的 「設計框架」&#xff0c;而非 LSTM&#xff08;具體單元結構&#xff09;或決策樹&#xff08;具體算法實體&#xff09;。CNN 的 「具體模型」 需要結合網絡…

愛基百客與真邁生物達成戰略合作,共推多組學科研服務升級

近日&#xff0c;武漢愛基百客生物科技有限公司&#xff08;以下簡稱“愛基百客”&#xff09;與真邁生物正式簽署戰略合作協議。此次戰略合作將聚焦表觀組學、單細胞時空組學等前沿科研領域&#xff0c;聯合打造基于自主創新技術的多組學科研服務方案&#xff0c;為科研人員提…