JS設(shè)計(jì)模式之責(zé)任鏈模式應(yīng)用詳解
責(zé)任鏈模式(Chain of Responsibility Pattern)
定義:
一種行為型設(shè)計(jì)模式,它允許多個(gè)對(duì)象按照順序處理請(qǐng)求,直到其中一個(gè)對(duì)象能夠處理請(qǐng)求為止。這樣的對(duì)象鏈被稱為責(zé)任鏈。
特點(diǎn):
在責(zé)任鏈模式中,每個(gè)處理請(qǐng)求的對(duì)象都有一個(gè)對(duì)下一個(gè)對(duì)象的引用,形成一個(gè)鏈條。
當(dāng)客戶端發(fā)送請(qǐng)求時(shí),請(qǐng)求會(huì)沿著鏈條傳遞,直到被某個(gè)處理器對(duì)象處理或者整個(gè)鏈條結(jié)束。
參與者:
抽象處理器(Abstract Handler):定義了處理請(qǐng)求的接口和維護(hù)下一個(gè)處理器的引用。通常實(shí)現(xiàn)為抽象類或接口。
具體處理器(Concrete Handler):具體實(shí)現(xiàn)了處理請(qǐng)求的方法。如果可以處理請(qǐng)求,則進(jìn)行處理;否則將請(qǐng)求傳遞給下一個(gè)處理器。
工作流程:
客戶端創(chuàng)建并初始化責(zé)任鏈中的處理器對(duì)象,并設(shè)置好它們的處理順序。
當(dāng)客戶端發(fā)送請(qǐng)求時(shí),請(qǐng)求從鏈條的開頭開始傳遞。
每個(gè)處理器檢查自己是否能夠處理請(qǐng)求,如果可以,則進(jìn)行處理并停止傳遞;否則將請(qǐng)求傳遞給下一個(gè)處理器。(這個(gè)過程必然會(huì)用到if else)
這個(gè)過程持續(xù)進(jìn)行,直到請(qǐng)求被處理或者整個(gè)鏈條結(jié)束。
優(yōu)點(diǎn):
解耦發(fā)送者和接收者,使得請(qǐng)求的發(fā)送者不需要知道哪個(gè)對(duì)象會(huì)處理請(qǐng)求。
可以動(dòng)態(tài)地添加或修改處理器對(duì)象,從而避免將請(qǐng)求的處理邏輯硬編碼到單個(gè)對(duì)象中,增加了代碼的可維護(hù)性和可擴(kuò)展性。
缺點(diǎn):
整個(gè)鏈條的長度可能會(huì)對(duì)性能產(chǎn)生影響,特別是在鏈條非常長時(shí)。
使用場景:
處理者是動(dòng)態(tài)的或者是不能預(yù)先確定的:有多個(gè)對(duì)象可以處理請(qǐng)求,但具體的處理者只在運(yùn)行時(shí)確定
希望將請(qǐng)求的發(fā)送者和接收者解耦,讓請(qǐng)求可以自由地在對(duì)象之間傳遞。
示例:
// 抽象處理器 class Handler { ? nextHandler: Handler|null = null; ? setNext(handler: Handler) { ? ? this.nextHandler = handler; ? } ? abstract handleRequest(request: number): void; } // 具體處理器1 class ConcreteHandler1 extends Handler { ? handleRequest(request: number) { ? ? request <= 10 ? console.log(`Request ${request} handled by ConcreteHandler1`) : this.nextHandler?.handleRequest(request); ? } } // 具體處理器2 class ConcreteHandler2 extends Handler { ? handleRequest(request: number) { ? ? request > 10 && request <= 20 ? console.log(`Request ${request} handled by ConcreteHandler2`) : this.nextHandler?.handleRequest(request); ? } } // 具體處理器3 class ConcreteHandler3 extends Handler { ? handleRequest(request) { ? ? request > 20 && request <= 80 ? console.log(`Request ${request} handled by ConcreteHandler3`) : this.nextHandler?.handleRequest(request); ? } } // 異常處理器 class ConcreteHandlerX extends Handler { ? handleRequest(request) { ? ? throw new Error(`Request ${request} can not be handled by ConcreteHandler chain`); ? } } // 創(chuàng)建處理對(duì)象 const handler1 = new ConcreteHandler1(); const handler2 = new ConcreteHandler2(); const handler3 = new ConcreteHandler3(); const errorhandler = new ConcreteHandlerX(); // 處理對(duì)象成鏈 handler1.setNext(handler2); handler2.setNext(handler3); handler3.setNext(errorhandler); // 客戶端發(fā)送請(qǐng)求 handler1.handleRequest(5); ? // 輸出: Request 5 handled by ConcreteHandler1 handler2.handleRequest(15); ?// 輸出: Request 15 handled by ConcreteHandler2 handler3.handleRequest(25); ?// 輸出: Request 25 handled by ConcreteHandler3 handler1.handleRequest(90); ?// 直接報(bào)錯(cuò)
原生實(shí)現(xiàn):
事件處理機(jī)制:在瀏覽器中,事件處理機(jī)制就是一個(gè)典型的責(zé)任鏈模式的應(yīng)用。當(dāng)事件發(fā)生時(shí),它會(huì)從目標(biāo)元素開始沿著 DOM 樹向上傳播,每個(gè)元素都有機(jī)會(huì)處理該事件。如果某個(gè)元素?zé)o法處理事件,它會(huì)將事件傳遞給它的父級(jí)元素,直到找到能夠處理事件的元素或者事件冒泡至根元素。
中間件(Middleware)模式:在 Web 開發(fā)中,中間件模式也是一種常見的責(zé)任鏈模式的應(yīng)用。例如,Express.js 框架中的中間件允許你按照順序添加不同的中間件函數(shù)來處理 HTTP 請(qǐng)求。請(qǐng)求將依次經(jīng)過這些中間件函數(shù),每個(gè)中間件函數(shù)都有可能對(duì)請(qǐng)求進(jìn)行處理、修改或者將請(qǐng)求傳遞給下一個(gè)中間件函數(shù)。
JavaScript Promise:Promise 是 JavaScript 中用于處理異步操作的一種機(jī)制。當(dāng)使用 Promise 鏈?zhǔn)秸{(diào)用時(shí),每個(gè) Promise 對(duì)象都有一個(gè)
then()
方法,可以將回調(diào)函數(shù)添加到鏈條中。當(dāng)前一個(gè) Promise 對(duì)象執(zhí)行完成后,它會(huì)自動(dòng)將結(jié)果傳遞給下一個(gè) Promise 對(duì)象,形成一個(gè)責(zé)任鏈?zhǔn)降奶幚怼?/p>jQuery Ajax:在 jQuery 的 Ajax 功能中,可以使用
$.ajax()
方法發(fā)送異步請(qǐng)求,并通過.done()
、.fail()
、.always()
等方法添加相應(yīng)的回調(diào)函數(shù)。這些回調(diào)函數(shù)可以按照順序連接起來,形成一個(gè)責(zé)任鏈,每個(gè)回調(diào)函數(shù)都有機(jī)會(huì)處理請(qǐng)求的結(jié)果。
總結(jié):
構(gòu)建抽象處理器類,然后子類具體處理器類重寫處理邏輯;實(shí)際化出不同的具體處理器類的實(shí)例對(duì)象,調(diào)用setNext方法成鏈,然后選擇鏈中某處作為入口,處理責(zé)任。
注意:不必從入口開始,因?yàn)榭赡茉谌腈溨熬鸵呀?jīng)判斷過了,范圍已經(jīng)縮小了。
擴(kuò)展:
鏈可以成環(huán),例如將handler3.setNext(errorhandler);
改成handler3.setNext(handler1);
, 從而責(zé)任傳遞永無停息,直到問題被解決。
用責(zé)任環(huán)結(jié)合定時(shí)器可以實(shí)現(xiàn)輪詢的效果。
到此這篇關(guān)于JS設(shè)計(jì)模式之責(zé)任鏈模式應(yīng)用詳解的文章就介紹到這了,更多相關(guān)JS責(zé)任鏈模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript給數(shù)組添加元素的6個(gè)方法
本文主要介紹了JavaScript給數(shù)組添加元素的6個(gè)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08微信小程序?qū)崿F(xiàn)點(diǎn)擊按鈕修改字體顏色功能【附demo源碼下載】
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)點(diǎn)擊按鈕修改字體顏色功能,涉及微信小程序wx:for循環(huán)讀取data數(shù)值及事件綁定修改元素屬性相關(guān)操作技巧,需要的朋友可以參考下2017-12-12移動(dòng)端點(diǎn)擊態(tài)處理的三種實(shí)現(xiàn)方式
在移動(dòng)端開發(fā)的時(shí)候,常常需要加點(diǎn)擊態(tài),就是當(dāng)用戶點(diǎn)擊某個(gè)URL時(shí),給相應(yīng)的標(biāo)簽添加按下效果樣式。這篇文章給大家分享了三種實(shí)現(xiàn)方法,包括偽類:active、webkit-tap-highlight-color和touch事件,下面來一起看看詳細(xì)的介紹吧。2017-01-01比較不錯(cuò)的函數(shù)式JavaScript編程指南教程
你是否知道JavaScript其實(shí)也是一個(gè)函數(shù)式編程語言呢?本指南將教你如何利用JavaScript的函數(shù)式特性。2008-05-05window.onload綁定多個(gè)事件的兩種解決方案
這篇文章主要介紹了window.onload綁定多個(gè)事件的兩種解決方案的相關(guān)資料,需要的朋友可以參考下2016-05-05JavaScript實(shí)現(xiàn)拼音排序的方法
本文將介紹JavaScript如何實(shí)現(xiàn)拼音排序 支持所有主流瀏覽器+中英文系統(tǒng)2012-11-11