javascript設計模式 – 職責鏈模式原理與用法例項分析
本文例項講述了javascript設計模式 – 職責鏈模式原理與用法。分享給大家供大家參考,具體如下:
介紹:很多情況下,在一個軟體系統中可以處理某個請求的物件不止一個。例如一個網路請求過來,需要有物件去解析request Body,需要有物件去解析請求頭,還需要有物件去對執行對應controller。請求一層層傳遞,讓每一個物件都基於請求完成自己的任務,然後將請求傳遞給下一個處理程式。是不是感覺有點中介軟體的感覺。
定義:職責鏈就是避免請求傳送者與接收者耦合在一起,讓多個物件都有可能接收請求。將這些物件連成一條鏈,並沿著鏈傳遞請求,直到有物件處理它為止。職責鏈模式是一種物件行為型模式。
場景:
示例:
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('畫一個超小的圓( 5以下 )'); } this.drawSmalCircle = function(){ console.log('畫一個小圓( 5-10 )'); } this.drawMediumCircle = function(){ console.log('畫一箇中圓 ( 10-15 )'); } this.drawBigCircle = function(){ console.log('畫一個大圓 ( 15-20 )'); } this.drawVeryBigCircle = function(){ console.log('畫一個超大的圓 ( 20以上 )'); } } var circle = new Circle(); circle.drawByRadius(30); //畫一個超大的圓 ( 20以上 )
觀察上面的程式碼,這是很常見的邏輯,通過引數來決定執行哪個方法。首先drawByRadius方法職責過重,其次這樣的方式在修改,新增時需要修改原始碼,不符合開關原則。
我們使用職責鏈模式重寫下:
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('執行:drawSmalCircle'); if(this.min < radius && radius < this.max){ console.log('畫一個小圓( 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('執行:drawMediumCircle'); if(this.min < radius && radius < this.max){ console.log('畫一箇中圓 ( 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('執行:drawBigCircle'); if(this.min < radius && radius < this.max){ console.log('畫一個大圓 ( 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) // 執行:drawSmalCircle // 執行:drawMediumCircle // 執行:drawBigCircle // 畫一個大圓 ( 20以上 circle.draw(15) // 執行:drawSmalCircle // 執行:drawMediumCircle // 畫一箇中圓 ( 10-20 ) // 執行:drawBigCircle circle.draw(5) // 執行:drawSmalCircle // 畫一個小圓( 10以下 ) // 執行:drawMediumCircle // 執行:drawBigCircle
以上就是職責鏈模式的例項程式碼,drawSmalCircle,drawMediumCircle,drawBigCircle稱為處理者類,處理者類儲存了下一級物件的引用,
當我每執行一次draw時,程式會挨個執行職責鏈上的每一個方法。
職責鏈模式分為純職責鏈和不純職責鏈,純的職責鏈在處理請求時,只能選擇全部處理不傳遞或者全部傳遞不處理。我們這裡的例子就是不純職責鏈。它允許處理完成後繼續向後傳遞。
職責鏈模式總結:
優點:
* 降低耦合,互相都不清楚執行順序以及執行處理的類。
* 請求物件僅需維持一個指向其後繼者的引用,簡化了物件的相互連線。
* 新增修改職責鏈結構方便,滿足開關原則。
缺點:
* 由於沒有明確接受者,可能職責鏈走到最後都沒有被正確處理。
* 職責鏈較長時會導致系統性能受影響。
* 建鏈不當,會造成迴圈呼叫,導致系統陷入死迴圈。
適用場景:
* 多個物件處理同一請求
* 動態建立執行順序,流程
感興趣的朋友可以使用線上HTML/CSS/JavaScript程式碼執行工具:http://tools.jb51.net/code/HtmlJsRun測試上述程式碼執行效果。
更多關於JavaScript相關內容感興趣的讀者可檢視本站專題:《javascript面向物件入門教程》、《JavaScript錯誤與除錯技巧總結》、《JavaScript資料結構與演算法技巧總結》、《JavaScript遍歷演算法與技巧總結》及《JavaScript數學運算用法總結》
希望本文所述對大家JavaScript程式設計有所幫助。