<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                [TOC] >[success] # 職責鏈前端角度 ~~~ 1.職責鏈就是不斷傳遞的過程,這個過程傳遞需要一個頭,也需要一個尾,為了防止 最后啥都找不到這個尾部通常是一個異常封裝 2.如下圖請求(傳入的參數) A B C D 對傳入的參數都能處理,但實際最后只有其中一個才能處理真正符合, 因此讓參數可以形成傳遞直到交給符合的鏈上一個環境,讓原本發散的形式形成鏈 ~~~ ![](https://img.kancloud.cn/c5/18/c5182fca59c93cc21be629ecfb80ff4d_1028x334.png) ![](https://img.kancloud.cn/98/bc/98bc759633aa4ba0af78a980ceac7940_890x276.png) >[info] ## 書中案例的需求分析 ~~~ 1.公司針對支付過定金的用戶有一定的優惠政策。在正式購買后,已經支付過 500 元定金的用 戶會收到 100 元的商城優惠券,200 元定金的用戶可以收到 50 元的優惠券,而之前沒有支付定金 的用戶只能進入普通購買模式,也就是沒有優惠券,且在庫存有限的情況下不一定保證能買到。 ~~~ >[danger] ##### 后臺和前端規定接口字段 ~~~ 1.orderType:表示訂單類型(定金用戶或者普通購買用戶),code 的值為 1 的時候是 500 元 定金用戶,為 2 的時候是 200 元定金用戶,為 3 的時候是普通購買用戶。 2.pay:表示用戶是否已經支付定金,值為 true 或者 false, 雖然用戶已經下過 500 元定金的 訂單,但如果他一直沒有支付定金,現在只能降級進入普通購買模式。 3.stock:表示當前用于普通購買的手機庫存數量,已經支付過 500 元或者 200 元定金的用 戶不受此限制。 ~~~ >[danger] ##### 正常直接寫代碼 ~~~ 1.直接判斷'orderType' 類型來根據不同類型做出不同的判斷 ~~~ ~~~ /* * @param{Number} orderType 訂單類型1 500定金,2 200 定金,3 普通用戶 * @param{Boolean} pay 是否支付定金true已支付 false 沒有支付 * @param{Number} stock 當前手機庫存 支付定金用戶不受影響 * */ var order = function (orderType,pay,stock) { if ( orderType === 1 ){ // 500 元定金購買模式 if ( pay === true ){ // 已支付定金 console.log( '500 元定金預購, 得到 100 優惠券' ); }else{ // 未支付定金,降級到普通購買模式 if ( stock > 0 ){ // 用于普通購買的手機還有庫存 console.log( '普通購買, 無優惠券' ); }else{ console.log( '手機庫存不足' ); } } } else if ( orderType === 2 ){ // 200 元定金購買模式 if ( pay === true ){ console.log( '200 元定金預購, 得到 50 優惠券' ); }else{ if ( stock > 0 ){ console.log( '普通購買, 無優惠券' ); }else{ console.log( '手機庫存不足' ); } } } else if ( orderType === 3 ){ if ( stock > 0 ){ console.log( '普通購買, 無優惠券' ); }else{ console.log( '手機庫存不足' ); } } } order( 1 , true, 500); ~~~ >[danger] ##### 用粗略的職責鏈模式來重構代碼 ~~~ 1.職責鏈的思路需要一個入口,一級一級傳遞知道找到符合自己執行方法 2.將500元,200元,和沒有定金的三種情況封裝成三個方法,500元是調用的開始,依次傳遞給 200元和沒有定金 3.下面代碼省去了部分條件語句,將三個模塊拆分成三個小函數,但調用必須從五百元為入口, 出現一個問題,傳遞請求的代碼被耦合在了業務函 會出現的問題: 違反'開放-封閉原則',如果有天我們要增加 300 元預訂或者去掉 200 元預訂,意味著就必須 改動這些業務函數內部。就像一根環環相扣打了死結的鏈條,如果要增加、拆除或者移動一個節點, 就必須得先砸爛這根鏈條。 ~~~ ~~~ // 500 元訂單 var order500 = function( orderType, pay, stock ){ if ( orderType === 1 && pay === true ){ console.log( '500 元定金預購, 得到 100 優惠券' ); }else{ order200( orderType, pay, stock ); // 將請求傳遞給 200 元訂單 }}; // 200 元訂單 var order200 = function( orderType, pay, stock ){ if ( orderType === 2 && pay === true ){ console.log( '200 元定金預購, 得到 50 優惠券' ); }else{ orderNormal( orderType, pay, stock ); // 將請求傳遞給普通訂單 } }; // 普通購買訂單 var orderNormal = function( orderType, pay, stock ){ if ( stock > 0 ){ console.log( '普通購買, 無優惠券' ); }else{ console.log( '手機庫存不足' ); } }; // 整個代碼的調用必須從五百元為入口 order500( 1 , true, 500); // 輸出:500 元定金預購, 得到 100 優惠券 order500( 1, false, 500 ); // 輸出:普通購買, 無優惠券 order500( 2, true, 500 ); // 輸出:200 元定金預購, 得到 500 優惠券 order500( 3, false, 500 ); // 輸出:普通購買, 無優惠券 order500( 3, false, 0 ); // 輸出:手機庫存不足 ~~~ >[danger] ##### 改進上面的代碼將職責鏈節點拆分成靈活 ~~~ 1.上面的代碼有個問題就是將職責的節點根據業務寫死,導致后期維護需要去改動整個職責鏈 ,改進思路就是每條職責到下一節點的內容是動態,然代碼動態和要請求的節點形成匹配 2.也就是說將代碼每個方法變成'職責鏈節點','這些節點和可以相互定義之間的運行順序' 3.需要'職責鏈上的節點','需要將這些節點鏈接成鏈式(即調用下個節點)','需要將請求的參數傳遞進節點中', 按照這三點的設想需要有一個中間調度方法具備上面三點一個'Chain'類在初始化構造函數時候 接受方法或者對象將其變成職責鏈節點,有兩個方法'setNextSuccessor'設置下一節點,'passRequest'調用 設置要傳遞的節點 4.總結一下職責鏈歸根到底他是一個鏈,如果是鏈就是一層套著一層,所有這個'China' 鏈的方法 肯定要有一個參數來接受自己下一個鏈調用,那successor 就是用來存下一個鏈的,到時候 我們吧這些China 鏈生成的對象相互嵌套,就形成了鏈,還要有一個'setNextSuccessor '來調用 我們封裝的方法,這里邏輯就是,如果你有'successor ' 下一層的鏈,你就要調用'successor '這個 鏈的'setNextSuccessor '讓你的下個鏈去調用你下下個鏈 ~~~ * 還是將三個方法單獨封裝,不過這一次不去指定他們的下一個節點 ~~~ // 500 元訂單 var order500 = function( orderType, pay, stock ){ if ( orderType === 1 && pay === true ){ console.log( '500 元定金預購, 得到 100 優惠券' ); }else{ return 'nextSuccessor'; // 我不知道下一個節點是誰,反正把請求往后面傳遞 }}; // 200 元訂單 var order200 = function( orderType, pay, stock ){ if ( orderType === 2 && pay === true ){ console.log( '200 元定金預購, 得到 50 優惠券' ); }else{ return 'nextSuccessor'; // 我不知道下一個節點是誰,反正把請求往后面傳遞 } }; // 普通購買訂單 var orderNormal = function( orderType, pay, stock ){ if ( stock > 0 ){ console.log( '普通購買, 無優惠券' ); }else{ console.log( '手機庫存不足' ); } }; ~~~ * 定義一個可以組合鏈子的類es5 ~~~ class China{ constructor(fn){ // 接受方法 this.fn = fn; // 要傳遞的下一 個 職責鏈節點 this.successor = null } // 當前節點中保存下一個節點對象 setNextSuccessor(){ return this.successor = successor } // 調用如果當前節點不能解決并且返回的是nextSuccessor // 則調用當前節點中 successor 存儲的下一個節點來解決 passRequest = function () { // 根據返回值來決定當前節點是否解決成功 var ret = this.fn.apply( this, arguments ); if ( ret === 'nextSuccessor' ){ return this.successor && this.successor.passRequest.apply( this.successor, arguments ); } return ret; } } ~~~ * 定義一個可以組合鏈子的類es5 ~~~ // 定義一個組合鏈子的類 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函數中形成 --- 職責鏈節點對象 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 ); // 輸出:500 元定金預購,得到 100 優惠券 chainOrder500.passRequest( 2, true, 500 ); // 輸出:200 元定金預購,得到 50 優惠券 chainOrder500.passRequest( 3, true, 500 ); // 輸出:普通購買,無優惠券 chainOrder500.passRequest( 1, false, 0 ); // 輸出:手機庫存不足 ~~~ >[danger] ##### 總結靈活創建節點的好處 ~~~ 1.如果增加一個三百元節點西藥做的就是直接增加一個節點即可 var order300 = function(){ // 具體實現略 }; chainOrder300= new Chain( order300 ); chainOrder500.setNextSuccessor( chainOrder300); chainOrder300.setNextSuccessor( chainOrder200); 2.書中對這一部分的'總結': 對于程序員來說,我們總是喜歡去改動那些相對容易改動的地方,就像改動框架的配置文件 遠比改動框架的源代碼簡單得多。在這里完全不用理會原來的訂單函數代碼,我們要做的只是增 加一個節點,然后重新設置鏈中相關節點的順序。 3.書中對這種實現現實代碼'好處'舉例: 本來我們要被迫維護一個充斥著條件分支語句的巨大的函數,在例子里的購買過程中只打印了 一條 log 語句。其實在現實開發中,這里要做更多事情,比如根據訂單種類彈出不同的浮層提示、 渲染不同的 UI 節點、組合不同的參數發送給不同的 cgi 等。 用了職責鏈模式之后,每種訂單都有各 自的處理函數而互不影響 ~~~ >[danger] ##### 職責鏈總結 ~~~ 1.'優點:' 2.1.職責鏈模式的最大優點就是解耦了請求發送者和 N 個接收者之間的復雜關 系, 由于不知道鏈中的哪個節點可以處理你發出的請求,所以你只需把請求傳遞給第 一個節點即可。 2.2.使用了職責鏈模式之后,鏈中的節點對象可以靈活地拆分重組。增加或者刪除一個節 點,或者改變節點在鏈中的位置都是輕而易舉的事情 2.3.請求并不是非得從鏈中的第一個 節點開始傳遞。可以控制開頭這樣減少傳遞 3.'缺點:' 3.1.從性能方面考慮,我們要避 免過長的職責鏈帶來的性能損耗。 3.2.運行到最后也沒找適合的職責節點,解決:在鏈尾增加一個保底的接受者節點來處理這種即將離 開鏈尾的請求。 ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看