iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 13
0
Modern Web

JS Design Pattern 系列 第 13

JS Design Pattern Day13-職責鏈模式 Chain of Responsibility(下)

Hi大家好,今天第13天了,Triskaidekaphobia 不知道打什麼只好玩個冷知識關鍵字XD

那今天繼續 職責鏈模式

好,接續上一篇。上一篇其實在設定下一節點的時候也可以這樣用,這樣看起更有鏈狀感

chainOrder500.setNextStage(chainOrder200).setNextStage(chainOrderNormal);

那如果有些方法是非同步的(例如ajax請求),我們原本返回的nextStage字串就已經無法滿足現況了,我們現在新增一個next方法,讓這些非同步請求的方法在可以進入下一節點的時候自行呼叫使用

Chain.prototype.next = function () {
    return this.stage && this.stage.passRequest.apply(this.stage, arguments);
};

let's try it

var fn1 = new Chain(function () {
    console.log('1');
    return 'nextStage';
});


var fn2 = new Chain(function () {
    var self = this;
    setTimeout(function () {
        console.log('2');
        self.next();
    }, 3000);
});

var fn3 = new Chain(function () {
    console.log('3');
});

fn1.setNextStage(fn2).setNextStage(fn3);

fn1.passRequest();

職責鏈的最大優點是可以將所有節點解藕,無論誰是請求者誰是接收者,在鏈結中可以任意的拆解或是新增節點,工程師也不必在意每個節點實際要做的內容,更可以手動指定起始節點,假設我們今天客戶流程更改,我們就只需要更改鏈結內節點順序就好。

但這樣的模式仍然有些缺點,首先是我們沒辦法保證請求一定會被處理,過程中的節點可能都會直接跳過這個請求,為避免這狀況發生,我們可以在鏈尾增加一個處理這種狀況的節點。另外一點也要注意的是,也許某些請求中大部分的節點都只是傳遞至下一節點的功能而已,從效能方面考量我們要避免過長的職責鏈所帶來的效能耗損。

在JS中有更容易更簡單做到職責鏈的方法,我們可以直接新增Function的類別函數,我們在這邊先叫此方法為after,實作上就是帶入下一個要執行的函數然後讓他執行,就這麼簡單,但一樣要先約定好執行下一個節點的方法,
在這裡我們一樣用回傳'nextStage'字串來表示

Function.prototype.after = function (fn) {
    var self = this;
    return function () {
        var ret = self.apply(this, arguments);
        if (ret === 'nextStage') {
            return fn.apply(this, arguments);
        }
        return ret;
    };
};

var order = order500.after(order200).after(orderNormal);
order(1, true, 10);

最後,我們在Day4文章迭代器模式中,我們有做一個迭代器來執行獲取上傳物件的方法,大致的code長這樣:

var iteratorUploadObj = function () {
    for (var i = 0, fn; fn = arguments[i++];) {
        var uploadObj = fn();
        if (uploadObj !== false) {
            return uploadObj;
        }
    }
};

var getUploadObjA = function () {
    //A方法實作內容
};

var getUploadObjB = function () {
    //B方法實作內容
};

var uploadObj = iteratorUploadObj(getUploadObjA, getUploadObjB);

在這裡我們就可以利用職責鏈模式直接讓這些方法直接接下去執行,不必要再多做個迭代器,要注意記得每個方法要回傳'nextStage'

var getUploadObjA = function () {
    //A方法實作內容
    return 'nextStage';
};

var getUploadObjB = function () {
    //B方法實作內容
    return 'nextStage';
};

var uploadObj = getUploadObjA.after(getUploadObjB);

其實職責鏈模式很常在不知不覺中被使用到,像是JS的原型鏈就有類似職責鏈模式的行為。

好,以上就是職責鏈模式。


上一篇
JS Design Pattern Day12-職責鏈模式 Chain of Responsibility(上)
下一篇
JS Design Pattern Day14-中介者模式 Mediator(上)
系列文
JS Design Pattern 30

尚未有邦友留言

立即登入留言