javascript設(shè)計(jì)模式 – 職責(zé)鏈模式原理與用法實(shí)例分析
本文實(shí)例講述了javascript設(shè)計(jì)模式 – 職責(zé)鏈模式原理與用法。分享給大家供大家參考,具體如下:
介紹:很多情況下,在一個(gè)軟件系統(tǒng)中可以處理某個(gè)請(qǐng)求的對(duì)象不止一個(gè)。例如一個(gè)網(wǎng)絡(luò)請(qǐng)求過(guò)來(lái),需要有對(duì)象去解析request Body,需要有對(duì)象去解析請(qǐng)求頭,還需要有對(duì)象去對(duì)執(zhí)行對(duì)應(yīng)controller。請(qǐng)求一層層傳遞,讓每一個(gè)對(duì)象都基于請(qǐng)求完成自己的任務(wù),然后將請(qǐng)求傳遞給下一個(gè)處理程序。是不是感覺(jué)有點(diǎn)中間件的感覺(jué)。
定義:職責(zé)鏈就是避免請(qǐng)求發(fā)送者與接收者耦合在一起,讓多個(gè)對(duì)象都有可能接收請(qǐng)求。將這些對(duì)象連成一條鏈,并沿著鏈傳遞請(qǐng)求,直到有對(duì)象處理它為止。職責(zé)鏈模式是一種對(duì)象行為型模式。
場(chǎng)景:我們繼續(xù)畫(huà)圓,我們準(zhǔn)備了兩組示例:
示例:
var Circle = function(){
this.radius = 0;
this.drawByRadius = function(radius){
if(radius < 5){
this.drawVerySmalCircle();
}else if(radius < 10){
this.drawSmalCircle();
}else if(radius < 15){
this.drawMediumCircle();
}else if(radius < 20){
this.drawBigCircle();
}else{
this.drawVeryBigCircle();
}
}
this.drawVerySmalCircle = function(){
console.log('畫(huà)一個(gè)超小的圓( 5以下 )');
}
this.drawSmalCircle = function(){
console.log('畫(huà)一個(gè)小圓( 5-10 )');
}
this.drawMediumCircle = function(){
console.log('畫(huà)一個(gè)中圓 ( 10-15 )');
}
this.drawBigCircle = function(){
console.log('畫(huà)一個(gè)大圓 ( 15-20 )');
}
this.drawVeryBigCircle = function(){
console.log('畫(huà)一個(gè)超大的圓 ( 20以上 )');
}
}
var circle = new Circle();
circle.drawByRadius(30);
//畫(huà)一個(gè)超大的圓 ( 20以上 )
觀察上面的代碼,這是很常見(jiàn)的邏輯,通過(guò)參數(shù)來(lái)決定執(zhí)行哪個(gè)方法。首先drawByRadius方法職責(zé)過(guò)重,其次這樣的方式在修改,新增時(shí)需要修改源代碼,不符合開(kāi)關(guān)原則。
我們使用職責(zé)鏈模式重寫(xiě)下:
var drawSmalCircle = function(min,max){
this.max = max;
this.min = min;
this.nextCircle;
this.setNextDraw = function(circle){
this.nextCircle = circle;
}
this.draw = function(radius){
console.log('執(zhí)行:drawSmalCircle');
if(this.min < radius && radius < this.max){
console.log('畫(huà)一個(gè)小圓( 10以下 )');
}
if(this.nextCircle){
this.nextCircle.draw(radius)
}
}
}
var drawMediumCircle = function(min,max){
this.max = max;
this.min = min;
this.nextCircle;
this.setNextDraw = function(circle){
this.nextCircle = circle;
}
this.draw = function(radius){
console.log('執(zhí)行:drawMediumCircle');
if(this.min < radius && radius < this.max){
console.log('畫(huà)一個(gè)中圓 ( 10-20 )');
}
if(this.nextCircle){
this.nextCircle.draw(radius)
}
}
}
var drawBigCircle = function(min,max){
this.max = max;
this.min = min;
this.nextCircle;
this.setNextDraw = function(circle){
this.nextCircle = circle;
}
this.draw = function(radius){
console.log('執(zhí)行:drawBigCircle');
if(this.min < radius && radius < this.max){
console.log('畫(huà)一個(gè)大圓 ( 20以上 )');
}
if(this.nextCircle){
this.nextCircle.draw(radius)
}
}
}
function initChain(){
var smalCircle = new drawSmalCircle(0,10);
var mediumCircle = new drawMediumCircle(10,20);
var bigCircle = new drawBigCircle(20,100);
smalCircle.setNextDraw(mediumCircle);
mediumCircle.setNextDraw(bigCircle);
return smalCircle;
}
var circle = initChain();
circle.draw(30)
// 執(zhí)行:drawSmalCircle
// 執(zhí)行:drawMediumCircle
// 執(zhí)行:drawBigCircle
// 畫(huà)一個(gè)大圓 ( 20以上
circle.draw(15)
// 執(zhí)行:drawSmalCircle
// 執(zhí)行:drawMediumCircle
// 畫(huà)一個(gè)中圓 ( 10-20 )
// 執(zhí)行:drawBigCircle
circle.draw(5)
// 執(zhí)行:drawSmalCircle
// 畫(huà)一個(gè)小圓( 10以下 )
// 執(zhí)行:drawMediumCircle
// 執(zhí)行:drawBigCircle
以上就是職責(zé)鏈模式的實(shí)例代碼,drawSmalCircle,drawMediumCircle,drawBigCircle稱為處理者類(lèi),處理者類(lèi)保存了下一級(jí)對(duì)象的引用,
當(dāng)我每執(zhí)行一次draw時(shí),程序會(huì)挨個(gè)執(zhí)行職責(zé)鏈上的每一個(gè)方法。
職責(zé)鏈模式分為純職責(zé)鏈和不純職責(zé)鏈,純的職責(zé)鏈在處理請(qǐng)求時(shí),只能選擇全部處理不傳遞或者全部傳遞不處理。我們這里的例子就是不純職責(zé)鏈。它允許處理完成后繼續(xù)向后傳遞。
職責(zé)鏈模式總結(jié):
優(yōu)點(diǎn):
* 降低耦合,互相都不清楚執(zhí)行順序以及執(zhí)行處理的類(lèi)。
* 請(qǐng)求對(duì)象僅需維持一個(gè)指向其后繼者的引用,簡(jiǎn)化了對(duì)象的相互連接。
* 新增修改職責(zé)鏈結(jié)構(gòu)方便,滿足開(kāi)關(guān)原則。
缺點(diǎn):
* 由于沒(méi)有明確接受者,可能職責(zé)鏈走到最后都沒(méi)有被正確處理。
* 職責(zé)鏈較長(zhǎng)時(shí)會(huì)導(dǎo)致系統(tǒng)性能受影響。
* 建鏈不當(dāng),會(huì)造成循環(huán)調(diào)用,導(dǎo)致系統(tǒng)陷入死循環(huán)。
適用場(chǎng)景:
* 多個(gè)對(duì)象處理同一請(qǐng)求
* 動(dòng)態(tài)創(chuàng)建執(zhí)行順序,流程
感興趣的朋友可以使用在線HTML/CSS/JavaScript代碼運(yùn)行工具:http://tools.jb51.net/code/HtmlJsRun測(cè)試上述代碼運(yùn)行效果。
更多關(guān)于JavaScript相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《javascript面向?qū)ο笕腴T(mén)教程》、《JavaScript錯(cuò)誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》及《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)》
希望本文所述對(duì)大家JavaScript程序設(shè)計(jì)有所幫助。
相關(guān)文章
JS實(shí)現(xiàn)手寫(xiě) forEach算法示例
這篇文章主要介紹了JS實(shí)現(xiàn)手寫(xiě) forEach算法,結(jié)合實(shí)例形式分析了JS實(shí)現(xiàn)手寫(xiě) forEach算法實(shí)現(xiàn)原理與相關(guān)操作技巧,需要的朋友可以參考下2020-04-04
javascript特殊文本輸入框網(wǎng)頁(yè)特效
這篇文章主要為大家詳細(xì)介紹了javascript特殊文本輸入框網(wǎng)頁(yè)特效,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09
BootStrap 動(dòng)態(tài)添加驗(yàn)證項(xiàng)和取消驗(yàn)證項(xiàng)的實(shí)現(xiàn)方法
這篇文章主要介紹了BootStrap 動(dòng)態(tài)添加驗(yàn)證項(xiàng)和取消驗(yàn)證項(xiàng)的實(shí)現(xiàn)方法的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09
Code Review 方法論與實(shí)踐總結(jié)梳理
這篇文章主要為大家介紹了Code Review 方法論與實(shí)踐總結(jié)梳理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
利用Query+bootstrap和js兩種方式實(shí)現(xiàn)日期選擇器
日期選擇器在我們平時(shí)開(kāi)發(fā)的時(shí)候經(jīng)常要用到,下面這篇文章主要給大家介紹了利用Query+bootstrap和js這兩種方式實(shí)現(xiàn)日期選擇器的方法,文中兩種方法都給出了詳細(xì)的示例代碼,有需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-01-01
JavaScript?ES6模塊導(dǎo)入和導(dǎo)出的方法
ES6在語(yǔ)言標(biāo)準(zhǔn)的層面上實(shí)現(xiàn)了模塊功能,而且實(shí)現(xiàn)的相當(dāng)簡(jiǎn)單,完全可以取代CommonJS和AMD規(guī)范,成為瀏覽器和服務(wù)器通用的模塊解決方案,下面這篇文章主要給大家介紹了關(guān)于ES6模塊導(dǎo)入和導(dǎo)出的方法,需要的朋友可以參考下2022-07-07

