日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JS设计模式五:职责链模式

發布時間:2023/12/6 javascript 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JS设计模式五:职责链模式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

職責鏈模式簡述

職責連是由多個不同的對象組成的,有發送者跟接收者,分別負責信息的發送跟接收,其中,鏈中第一個對象是 職責連是由多個不同的對象組成的,發送者是發送請求的對象,接收者接收請求并且對其進行處理或傳遞的對象。基本流程如下:

  • 發送者知道鏈中的第一個接收者,它向這個接收者發送該請求。
  • 每一個接收者都對請求進行分析,然后要么處理它,要么它往下傳遞。
  • 每一個接收者知道其他的對象只有一個,即它在鏈中的下家(successor)。
  • 如果沒有任何接收者處理請求,那么請求會從鏈中離開。
  • 職責鏈模式是個鏈式結構,請求在鏈中的節點之間依次傳遞,直到有一個對象能處理該請求為止。如果沒有任何對象處理該請求的話,那么請求就會從鏈中離開。

    實戰

    以電商網站抽獎為例,規則如下:

  • 用戶充值500元,可以100%中獎100元紅包
  • 用戶充值200元,可以100%中獎20元紅包
  • 用戶不充值,也可以抽獎,但概率極低。
  • 用戶充值失敗,按不充值處理。
  • 常規實現

    首先需要定義幾個字段:

  • orderType:充值類型。如果值為1的話,說明是充值500元的用戶,如果為2的話,說明是充值200元的用戶,如果是3的話,說明是沒有充值的用戶。
  • isPay:是否已經成功充值了。 如果該值為true的話,說明已經成功充值了,否則的話說明沒有充值成功;就當作普通用戶來購買。
  • count:表示數量。普通用戶抽獎,如果數量有的話,就可以拿到優惠卷,否則的話,不能拿到優惠卷。
  • 實現如下:

    var order = function(orderType,isPay,count) {if(orderType == 1) { // 用戶充值500元if(isPay == true) { // 如果充值成功的話,100%中獎console.log("親愛的用戶,您中獎了100元紅包了");}else {// 充值失敗,就當作普通用戶來處理中獎信息if(count > 0) {console.log("親愛的用戶,您已抽到10元優惠卷");}else {console.log("親愛的用戶,請再接再厲哦");}}}else if(orderType == 2) { // 用戶充值200元if(isPay == true) { // 如果充值成功的話,100%中獎console.log("親愛的用戶,您中獎了20元紅包了");}else {// 充值失敗,就當作普通用戶來處理中獎信息if(count > 0) {console.log("親愛的用戶,您已抽到10元優惠卷");}else {console.log("親愛的用戶,請再接再厲哦");}}}else if(orderType == 3) {// 普通用戶來處理中獎信息if(count > 0) {console.log("親愛的用戶,您已抽到10元優惠卷");}else {console.log("親愛的用戶,請再接再厲哦");}} }; 復制代碼

    如上代碼,雖然實現了需求,但存在的問題也比較突出: 一、業務邏輯代碼耦合度太高,如果想增加條件,比如充值300可以中獎150元紅包,這時候就很容易改出問題 二、冗余代碼太多,普通用戶抽獎的代碼是可以單獨抽離出來的

    職責鏈實現

    function order500(orderType,isPay,count){if(orderType == 1 && isPay == true) {console.log("親愛的用戶,您中獎了100元紅包了");}else {//我不知道下一個節點是誰,反正把請求往后面傳遞return "nextSuccessor";} }; function order200(orderType,isPay,count) {if(orderType == 2 && isPay == true) {console.log("親愛的用戶,您中獎了20元紅包了");}else {//我不知道下一個節點是誰,反正把請求往后面傳遞return "nextSuccessor";} }; function orderNormal(orderType,isPay,count){// 普通用戶來處理中獎信息if(count > 0) {console.log("親愛的用戶,您已抽到10元優惠卷");}else {console.log("親愛的用戶,請再接再厲哦");} } // 下面需要編寫職責鏈模式的封裝構造函數方法 var Chain = function(fn){this.fn = fn;this.successor = null; }; Chain.prototype.setNextSuccessor = function(successor){return this.successor = successor; } // 把請求往下傳遞 Chain.prototype.passRequest = function(){var ret = this.fn.apply(this,arguments);if(ret === 'nextSuccessor') {return this.successor && this.successor.passRequest.apply(this.successor,arguments);}return ret; } //現在我們把3個函數分別包裝成職責鏈節點: var chainOrder500 = new Chain(order500); var chainOrder200 = new Chain(order200); var chainOrderNormal = new Chain(orderNormal);// 然后指定節點在職責鏈中的順序 chainOrder500.setNextSuccessor(chainOrder200); chainOrder200.setNextSuccessor(chainOrderNormal);//最后把請求傳遞給第一個節點: chainOrder500.passRequest(1,true,500); // 親愛的用戶,您中獎了100元紅包了 chainOrder500.passRequest(2,true,500); // 親愛的用戶,您中獎了20元紅包了 chainOrder500.passRequest(3,true,500); // 親愛的用戶,您已抽到10元優惠卷 chainOrder500.passRequest(1,false,0); // 親愛的用戶,請再接再厲哦 復制代碼

    如上代碼: 一、分別編寫order500,order200,orderNormal三個函數,處理自己的業務邏輯,如果自己的函數不能處理的話,就返回字符串nextSuccessor 往后面傳遞 二、封裝Chain構造函數,接收fn做為參數,且帶有屬性successor。實例化后的Chain類型的對象,就像一個一個獨立存在的節點。 三、Chain構造函數原型上有2個方法,分別是setNextSuccessor 和 passRequest。setNextSuccessor 方法指定了節點在職責鏈中的順序,passRequest方法是將請求轉移到職責鏈的下一個節點。

    如上文提到的,假設需要實現“充值300中獎150元”,我們可以編寫order300這個函數,通過Chain包裝起來,指定在職責鏈中的順序即可。業務邏輯的代碼不需要任何處理。

    現在又有一個問題,我們在開發中經常會碰到ajax異步請求,如果我們用上面的做法,就不生效了。由此,便引出了異步的職責鏈來解決這個問題。我們給Chain類再增加一個原型方法Chain.prototype.next,表示手動傳遞請求給職責鏈中的一下個節點。

    function Fn1() {console.log(1);return "nextSuccessor"; } function Fn2() {console.log(2);var self = this;setTimeout(function(){self.next();},1000); } function Fn3() {console.log(3); } // 下面需要編寫職責鏈模式的封裝構造函數方法 var Chain = function(fn){this.fn = fn;this.successor = null; }; Chain.prototype.setNextSuccessor = function(successor){return this.successor = successor; } // 把請求往下傳遞 Chain.prototype.passRequest = function(){var ret = this.fn.apply(this,arguments);if(ret === 'nextSuccessor') {return this.successor && this.successor.passRequest.apply(this.successor,arguments);}return ret; } Chain.prototype.next = function(){return this.successor && this.successor.passRequest.apply(this.successor,arguments); } //現在我們把3個函數分別包裝成職責鏈節點: var chainFn1 = new Chain(Fn1); var chainFn2 = new Chain(Fn2); var chainFn3 = new Chain(Fn3);// 然后指定節點在職責鏈中的順序 chainFn1.setNextSuccessor(chainFn2); chainFn2.setNextSuccessor(chainFn3);chainFn1.passRequest(); // 打印出1,2 過1秒后 會打印出3 復制代碼

    如上代碼,當執行到F2時,遇到了定時器異步函數,當定時器執行結束后,調用了next方法,手動將請求交給職責鏈中的下一個節點,因此過了一秒后,會打印3。

    總結

    優點

  • 解耦了請求發送者和度個接收者之間的復雜關系,不需要知道鏈中哪個節點能處理你的請求,只需要把請求傳遞到第一個節點即可。
  • 鏈中的節點對象可以靈活地拆分重組,增加或刪除一個節點,或者改變節點的位置都是很簡單的事情。
  • 我們還可以手動指定節點的起始位置,并不是說非得要從其實節點開始傳遞的.
  • 缺點

    職責鏈模式中多了一點節點對象,可能在某一次請求過程中,大部分節點沒有起到實質性作用,他們的作用只是讓請求傳遞下去,從性能方面考慮,避免過長的職責鏈提高性能。

    總結

    以上是生活随笔為你收集整理的JS设计模式五:职责链模式的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。