成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

傳遞請(qǐng)求之職責(zé)鏈模式

wslongchen / 3407人閱讀

摘要:想一想,這個(gè)和我們的迭代器模式有著異曲同工的妙處,迭代器模式同樣也是遍歷選出最優(yōu)解,但是相比而言,職責(zé)鏈模式的直觀性個(gè)書(shū)寫(xiě)的幸福感是遠(yuǎn)遠(yuǎn)超過(guò)迭代器模式的。

職責(zé)鏈模式其實(shí)很好理解,由于一個(gè)鏈字出賣(mài)了它的靈魂。我們可以從這個(gè)字得到很大的提示。首先這個(gè)模式一定有傳遞性,而且,節(jié)點(diǎn)是可以重復(fù)拼接的,并且每個(gè)節(jié)點(diǎn)都具有一定的過(guò)濾功能,一定的職責(zé)。

是不是想起了組合模式里的一些內(nèi)容呢? 是的,他們兩個(gè)有著天然的類(lèi)似點(diǎn),不過(guò)組合模式主要職責(zé)是給執(zhí)行者添加一些列行為,而不區(qū)分內(nèi)部的執(zhí)行。職責(zé)鏈模式則會(huì)強(qiáng)調(diào)內(nèi)部的細(xì)節(jié),他可以手動(dòng)傳遞權(quán)限,手動(dòng)終止權(quán)限。

舉個(gè)栗子吧:

小時(shí)候,俺是一個(gè)學(xué)渣,平時(shí)作業(yè)都不會(huì)做,但是老師硬性要求你做。沒(méi)辦法,只有去借鑒學(xué)霸的作業(yè)。首先,我們班人都超級(jí)好,我做在最后一排,然后

我問(wèn)前一排的妹紙: 嗨,小芳,你的作業(yè)能給我看看嘛?
小芳: 我作業(yè)沒(méi)做呢?我?guī)湍銌?wèn)問(wèn)前面的。
小芳: 小明,你作業(yè)做完了嗎?能給我看看嘛?
小明: 我作業(yè)沒(méi)做呢?我?guī)湍銌?wèn)問(wèn)前面的。
小明: 小吉,你作業(yè)做完了嗎?能給我看看嘛?
小吉: 做完了,給你吧。

恩,good,事情圓滿解決。完美的體現(xiàn)出,職責(zé)鏈的內(nèi)涵,上一節(jié)點(diǎn),只要知道下一個(gè)節(jié)點(diǎn)的接口,so that enough。 如果本身節(jié)點(diǎn)能夠完成任務(wù),則將結(jié)果輸出,終止傳遞。

用代碼標(biāo)識(shí)即為:

function Me (flag){
    if(flag===1){
        console.log("I can do this homeword");
    }else{
        console.log("I can"t :(, but u can do this ?");
        XiaoFang(flag);
    }
}
function XiaoFang (flag){
    if(flag===1){
        console.log("I can do this homeword");
    }else{
        console.log("I can"t :(, but u can do this ?");
        XiaoJi(flag);
    }
}
function XiaoJi (flag){
    if(flag===0){
        console.log("I can do this homeword");
    }else{
        console.log("I can"t :(, but u can do this ?");
            //...繼續(xù)詢(xún)問(wèn)下一個(gè)人
    }
}
Me(0);

沒(méi)錯(cuò),職責(zé)鏈的主要內(nèi)涵就是,如果你不行,在問(wèn)問(wèn)下一個(gè)人行不行。。。但是上面代碼讓我有種想kill people的沖動(dòng)(不是寫(xiě)的爛,是寫(xiě)的太爛了),唯一能夠表?yè)P(yáng)他的就是,知道職責(zé)鏈模式的原理。所以為了情懷,我們需要給上面的代碼換一身皮.

function Chain(fn){
    this.fn = fn;
    this.nextExer = null;
}
Chain.prototype.setNext = function(obj){
    this.nextExer = obj;
}
Chain.prototype.exe = function(flag){
    var result = this.fn.apply(this,arguments);
    if(result === "next"){
        this.next(flag);
    }
}
Chain.prototype.next = function(){
    return this.nextExer.exe.apply(this.nextExer,arguments)
}
var fn1 = new Chain(function(flag){
    if(flag===1){
        console.log("I can do this homework");
    }else{
        console.log("I can"t do this homework");
        return "next";
    }
});
var fn2 = new Chain(function(flag){
    if(flag===1){
        console.log("I can do this homework");
    }else{
        console.log("I can"t do this homework");
        return "next";
    }
})
var fn3 = new Chain(function(flag){
    if(flag===0){
        console.log("I can do this homework");
    }else{
        console.log("I can"t do this homework");
        return "next";
    }
})
fn1.setNext(fn2);
fn2.setNext(fn3);
fn1.exe(0);

雖然,上面這段代碼看起來(lái)清晰很多,使用next調(diào)用下一個(gè)函數(shù),使用exe初始化.但是看起來(lái)在setNext哪里有點(diǎn)啰嗦。我們?cè)囍倪M(jìn):

Chain.prototype.setNext = function(obj){
    this.nextExer = obj;
    return obj;
}
fn1.setNext(fn2).setNext(fn3);
fn1.exe(0);

只需要將setNext哪里返回一個(gè)Obj,就可以得到完美的鏈?zhǔn)秸{(diào)用了??梢詮纳厦娴拇a中看出一些端倪,在職責(zé)鏈模式中,我們需要規(guī)定,在每個(gè)exe執(zhí)行過(guò)后需要設(shè)置一個(gè)result,并且這個(gè)result必須能明確的標(biāo)識(shí)下一個(gè)到底繼不繼續(xù)。

當(dāng)然,要知道,這個(gè)職責(zé)鏈模式并不是一定要把管理權(quán)交給內(nèi)部執(zhí)行,你當(dāng)然也可以在外面進(jìn)行判斷和設(shè)置。

var fn2 = new Chain(function(flag){
    console.log("I can"t do this homework");
    this.nextExer.fn(0);  //手動(dòng)執(zhí)行下一個(gè)
})

通過(guò)上面的步驟,可以在外部直接判斷,是否執(zhí)行下一個(gè)。所以職責(zé)模式的寫(xiě)法也是很多的。

職責(zé)鏈的利弊

而且,職責(zé)鏈最大的一個(gè)好處就是,你可以從鏈中,任意一個(gè)節(jié)點(diǎn)開(kāi)始遍歷。 我們用上面那個(gè)例子體會(huì)一下。

假如,我前面座的童鞋,我和他都同時(shí)喜歡一女生,所以我倆關(guān)系超差。我當(dāng)然不能問(wèn)情敵要作業(yè)啦,這時(shí)候,我可以再往前一個(gè)同學(xué)問(wèn)。利用職責(zé)模式就為.

xiaoMing.setNext(xiaoFang).setNext(xiaoJi);
//改寫(xiě),直接從小芳開(kāi)始
xiaoFang.setNext(xiaoJi);

這應(yīng)該算是職責(zé)鏈模式的一大特色,但是這個(gè)也不是沒(méi)有問(wèn)題的,就是我們需要在最后一個(gè)節(jié)點(diǎn)上加上判斷,表示如果沒(méi)有其他處理程序,而且在該節(jié)點(diǎn)上也不成立的話,則需要拋出一個(gè)錯(cuò)誤,或者做出相應(yīng)的說(shuō)明. 并且,我們每次請(qǐng)求的時(shí)候,都會(huì)從節(jié)點(diǎn)鏈的開(kāi)始進(jìn)行遍歷,這樣很可能會(huì)造成性能的損失,所以這里需要注意的是,不要設(shè)置太長(zhǎng)的職責(zé)鏈。

使用AOP

這里AOP指的是面向切面編程,即將其他函數(shù)動(dòng)態(tài)的加入到一個(gè)函數(shù)中,比如before & after. 我們仔細(xì)想想,一個(gè)隊(duì)列無(wú)外乎就是在前在后的關(guān)系,所以一個(gè)before和after已經(jīng)算是萬(wàn)能的了(排除你有動(dòng)態(tài)刪除的需求)。

Function.prototype.after = function(fn){
    var _this = this;
    return function(){
        var res = _this.apply(this,arguments);
        if(!res){  //值為Boolean
            return fn.apply(this,arguments);
        }
        return res;
    }
}
Function.prototype.before = function(fn){
    var _this = this;
    return function(){
        fn.apply(this,arguments);
        return    _this.apply(this,arguments);
    }
}

上面已經(jīng)將AOP中兩個(gè)最重要的before和after添加到Function的原型里面了。

現(xiàn)在我們可以使用這兩把三相之力開(kāi)啟職責(zé)鏈模式

XiaoMing.after(XiaoFang).after(XiaoJi);

我操,完美啊,通俗易懂哎喂。

如果我們需要加上判斷的話,可以直接在after和before里面寫(xiě)

//只舉before的例子吧
Function.prototype.before = function(fn){
    var _this = this;
    return function(){
        var res = fn.apply(this,arguments);  //值為Boolean,表示是否繼續(xù)向下傳遞
        if(res===false){  //如果返回不成立,則繼續(xù)向下傳遞
            return    _this.apply(this,arguments);
        }
    }
}

function Xiaoming(){
    console.log("I can do this homework");
    return "ok"; //中斷返回,當(dāng)然這里你可以隨便定義,除了"next"
}
function XiaoFang(){
    console.log("I can"t do this homework");
    return "next";
}
Xiaoming. before(XiaoFang)();
職責(zé)鏈模式之干貨

我們這里再次回憶一下職責(zé)鏈模式的用處,將一個(gè)請(qǐng)求依照一條鏈傳遞,如果有個(gè)滿足則斷開(kāi)傳遞,返回結(jié)果。 想一想,這個(gè)和我們的迭代器模式有著異曲同工的妙處,迭代器模式同樣也是遍歷選出最優(yōu)解,但是相比而言,職責(zé)鏈模式的直觀性個(gè)書(shū)寫(xiě)的幸福感是遠(yuǎn)遠(yuǎn)超過(guò)迭代器模式的。

在寫(xiě)一些hacks的時(shí)候,難免會(huì)用到if...else if...判斷語(yǔ)句,上次我們使用迭代器模式完成這樣的功能,但是效果不是很理想,這里我們使用職責(zé)鏈模式完成。

事件模式的選擇函數(shù)

Function.prototype.after = function(fn){
    var _this = this;
    return function(){
        var res = _this.apply(this,arguments);
        if(res==="next"){  //值為Boolean
            return fn.apply(this,arguments);
        }
        return res;
    }
}
var bind = (function() {
    var DOM2 = function() {
        if (document.addEventListener) {
            return function(ele, fn, type) {
                ele.addEventListener(type, () => {
                    fn();
                }, false);
            }
        } else {
            return "next";
        }
    };
    var IE = function() {
        if (document.attachEvent) {
            return function(ele, fn, type) {
                ele.attachEvent(type, fn);
            }
        } else {
            return "next";
        }
    };
    var DOM0 = function(){
        return function(ele, fn, type) {
            ele[`on${type}`] = () => {
                fn();
            };
        }
    }
    return DOM2.after(IE).after(DOM0)();
})();
console.log(bind);

恩,以上結(jié)果只是一個(gè)簡(jiǎn)單地示范。 這里需要提個(gè)醒,職責(zé)鏈模式是設(shè)計(jì)模式中最容易忘記的模式之一,因?yàn)樗糜玫讲唤心J?。所以,職?zé)鏈模式的用法也是很多的,希望大家多多探索,將自己學(xué)到的只是分享出來(lái),這是,極好的呀!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/78510.html

相關(guān)文章

  • Java設(shè)計(jì)模式職責(zé)模式

    摘要:簡(jiǎn)介職責(zé)鏈模式有時(shí)候也叫責(zé)任鏈模式,它是一種對(duì)象行為的設(shè)計(jì)模式。中的就是使用了責(zé)任鏈模式。純的責(zé)任鏈模式的實(shí)際例子很難找到,一般看到的例子均是不純的責(zé)任鏈模式的實(shí)現(xiàn)。如果堅(jiān)持責(zé)任鏈不純便不是責(zé)任鏈模式,那么責(zé)任鏈模式便不會(huì)有太大意義了。 Java設(shè)計(jì)模式之職責(zé)鏈模式 前幾天復(fù)習(xí)java的異常處理時(shí),接觸到了責(zé)任鏈模式。在企業(yè)級(jí)應(yīng)用中,從前臺(tái)發(fā)過(guò)來(lái)的請(qǐng)求在后臺(tái)拋出異常,異常處理的設(shè)計(jì)一般...

    bergwhite 評(píng)論0 收藏0
  • JS每日一題:設(shè)計(jì)模式-如何理解職責(zé)模式?

    摘要:提交請(qǐng)求的對(duì)象并不明確知道哪一個(gè)對(duì)象將會(huì)處理它也就是該請(qǐng)求有一個(gè)隱式的接受者。 20190412期 設(shè)計(jì)模式-如何理解職責(zé)鏈模式? 定義: 使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求,從而避免請(qǐng)求的發(fā)送者和接收者之間的耦合關(guān)系,將這些對(duì)象連成一條鏈,并沿著這條鏈傳遞該請(qǐng)求,直到有一個(gè)對(duì)象處理它為止 也就是說(shuō),請(qǐng)求以后,從第一個(gè)對(duì)象開(kāi)始,鏈中收到請(qǐng)求的對(duì)象要么親自處理它,要么轉(zhuǎn)發(fā)給鏈中的下一個(gè)候選者。提...

    lifesimple 評(píng)論0 收藏0
  • JavaScript設(shè)計(jì)模式----職責(zé)模式

    摘要:使用面向切面編程來(lái)快速的創(chuàng)建職責(zé)鏈的具體概念可以參考裝飾者模式實(shí)現(xiàn)職責(zé)鏈簡(jiǎn)單又巧妙,但這種把函數(shù)疊在一起的方式,同時(shí)也疊加了函數(shù)的作用域,如果鏈條太長(zhǎng)的話,也會(huì)對(duì)性能造成太大的影響。在開(kāi)發(fā)中,職責(zé)鏈模式是最容易被忽視的模式之一。 聲明:這個(gè)系列為閱讀《JavaScript設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐》 ----曾探@著一書(shū)的讀書(shū)筆記 1.職責(zé)鏈模式的定義 2. 2.1 簡(jiǎn)單職責(zé)鏈模式 2....

    boredream 評(píng)論0 收藏0
  • JS設(shè)計(jì)模式——職責(zé)模式

    摘要:用實(shí)現(xiàn)職責(zé)鏈這里使用變量存儲(chǔ)上一個(gè)函數(shù),存儲(chǔ)的是最后一個(gè)調(diào)用返回的函數(shù)。理解了過(guò)程也就會(huì)知道這句代碼是為后面的函數(shù)準(zhǔn)備的建議如果某塊功能中存在大量的可以考慮使用職責(zé)鏈模式 職責(zé)鏈模式 1. 職責(zé)鏈定義 使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求,從而避免請(qǐng)求的發(fā)送者和接受者之間的耦合關(guān)系,將對(duì)象連成一條鏈,并沿著這個(gè)鏈傳遞該請(qǐng)求,直到有一個(gè)對(duì)象處理它為止 2.職責(zé)鏈優(yōu)點(diǎn) 請(qǐng)求發(fā)送者只需要知道鏈中的第一...

    piapia 評(píng)論0 收藏0
  • 一起學(xué)設(shè)計(jì)模式 - 責(zé)任模式

    摘要:責(zé)任鏈模式屬于行為型模式的一種,將請(qǐng)求沿著一條鏈傳遞,直到該鏈上的某個(gè)對(duì)象處理它為止。責(zé)任鏈模式通過(guò)將請(qǐng)求和處理分離開(kāi)來(lái),以進(jìn)行解耦。源碼分析我們經(jīng)常使用的就使用到了責(zé)任鏈模式,創(chuàng)建一個(gè)除了要在應(yīng)用中做相應(yīng)配置外,還需要實(shí)現(xiàn)接口。 責(zé)任鏈模式(Chain Of Responsibility Pattern)屬于行為型模式的一種,將請(qǐng)求沿著一條鏈傳遞,直到該鏈上的某個(gè)對(duì)象處理它為止。 ...

    SoapEye 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<