js设计模式之职责链模式
一. 初始職責鏈模式
????????定義:使多個對象都有機會處理請求,從而避免請求的發送者和接收者的關系,將這個對象連成一條鏈,并沿著一條鏈傳遞該請求,直到一個對象處理它為止。
可能有點晦澀難懂,我們來看一個例子,比如說你媽讓你出去打醬油,此時我的請求就是買一瓶醬油回來,你會出門先去離你家最近的超市買醬油,如果沒有,你會去下一個超市,知道有一個超市買到了醬油,也就結束了這條鏈的傳遞,超市就相當于處理請求的一條對象鏈,這就是職責鏈模式,我們想辦法用代碼實現它。
二. 代碼實現
需求:我們來實現生活中的一個例子,商品的優惠活動,有三種情況,第一種是500元訂金100元優惠券,第二種是200元訂金50元優惠券,第三種是無優惠。
? ? ? ? 此時我們首先想到的做法肯定使用條件分支來判斷屬于哪一種優惠,雖然可以達到目的,但是代碼的可維護性太低,我們可以使用職責鏈模式來實現。
1. 靈活可拆分的職責鏈節點
? ? ? ? 分析:首先我們將每一次優惠作為單獨封裝,判斷請求是否滿足此次優惠條件,如果不滿足,則向下傳遞,直到滿足優惠條件為止。
let order500 = function( orderType, pay, stock ) {if( orderType == 1 && pay == true) {console.log(" 500元訂金,得到100元優惠券");}else{return 'nextSuccessor';}}let order200 = function( orderType, pay, stock ){if( orderType == 2 && pay == true ) {console.log(" 200元訂金,得到50元優惠券");}else{return 'nextSuccessor';}}let orderNormal = function( orderType, pay, stock ) {if(stock > 0) {console.log("普通購買,無優惠券");}else{console.log("手機庫存不足");}}// 包裝節點let Chain = function( fn ){this.fn = fn;this.successor = null;}Chain.prototype.setNextSuccessor = function( successor ) {return this.successor = successor;}Chain.prototype.passRequest = function() {let ret = this.fn.apply(this, arguments);if( ret === "nextSuccessor") {return this.successor && this.successor.passRequest.apply(this.successor, arguments);}return ret;}// 創建職責鏈節點let chainOrder500 = new Chain( order500 );let chainOrder200 = new Chain( order200 );let chainOrderNormal = new Chain( orderNormal );chainOrder500.setNextSuccessor( chainOrder200 ).setNextSuccessor(chainOrderNormal);chainOrder500.passRequest(1, true, 500);chainOrder500.passRequest(2, true, 500);2. 異步的職責鏈
? ? ? ? 分析:有時我們的請求可能不是那么順暢,比如獲取請求時,請求數據拿回來可能有延遲,我們根據拿到的數據來判斷是否進行再次的請求,因此我們需要設置主動向下一節點傳遞請求,通過異步實現。
// 包裝節點let Chain = function( fn ){this.fn = fn;this.successor = null;}Chain.prototype.setNextSuccessor = function( successor ) {return this.successor = successor;}Chain.prototype.passRequest = function() {let 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);}// 創建職責鏈節點let fn1 = new Chain(()=>{console.log(1);return 'nextSuccessor';})let fn2 = new Chain(function(){console.log(2);let self = this;setTimeout(()=>{self.next();}, 2000);})let fn3 = new Chain(()=>{console.log(3);})fn1.setNextSuccessor( fn2 ).setNextSuccessor( fn3 );fn1.passRequest();3. 用 AOP 實現職責鏈
分析:用 AOP 來實現雖然簡單巧妙,但是將函數疊在一起,也疊加了函數的作用域,如果兩天太長會對性能有較大影響。
Function.prototype.after = function( fn ) {let self = this;return function() {let ret = self.apply(this, arguments);if(ret === 'nextSuccessor') {fn.apply( this, arguments );}return ret;}}let order = order500.after( order200 ).after( orderNormal );order(3, true, 500);三. 總結
? ? ? ? 優點:1.? 解耦了請求的發送者和 N 個接收者之間的 復雜關系
? ? ? ? ? ? ? ? ? ?2. 每個對象可有靈活拆分,控制請求的入口和長度
? ? ? ? 缺點: 1. 可能某次傳遞中大部分節點都只是作為傳遞,并沒有多大的用處,造成性能損耗
無論是作用域鏈,原型鏈,還是冒泡事件中都合適的應用了職責鏈模式。職責鏈模式還可以和組合模式結合在一起,用來連接部件和父部件,或者提高組合對象的效率。
總結
以上是生活随笔為你收集整理的js设计模式之职责链模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux的FHS目录结构简要介绍
- 下一篇: 常用设计模式——职责链模式