国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

5 分鐘即可掌握的 JavaScript 裝飾者模式與 AOP

chunquedong / 1166人閱讀

摘要:下裝飾者的實(shí)現(xiàn)了解了裝飾者模式和的概念之后,我們寫一段能夠兼容的代碼來實(shí)現(xiàn)裝飾者模式原函數(shù)拍照片定義函數(shù)裝飾函數(shù)加濾鏡用裝飾函數(shù)裝飾原函數(shù)這樣我們就實(shí)現(xiàn)了抽離拍照與濾鏡邏輯,如果以后需要自動上傳功能,也可以通過函數(shù)來添加。

什么是裝飾者模式

當(dāng)我們拍了一張照片準(zhǔn)備發(fā)朋友圈時,許多小伙伴會選擇給照片加上濾鏡。同一張照片、不同的濾鏡組合起來就會有不同的體驗(yàn)。這里實(shí)際上就應(yīng)用了裝飾者模式:是通過濾鏡裝飾了照片。在不改變對象(照片)的情況下動態(tài)的為其添加功能(濾鏡)。

需要注意的是:由于 JavaScript 語言動態(tài)的特性,我們很容易就能改變某個對象(JavaScript 中函數(shù)是一等公民)。但是我們要盡量避免直接改寫某個函數(shù),這會導(dǎo)致代碼的可維護(hù)性、可擴(kuò)展性變差,甚至?xí)廴酒渌麡I(yè)務(wù)。

什么是 AOP

想必大家對"餐前洗手、飯后漱口"都不陌生。這句標(biāo)語其實(shí)就是 AOP 在生活中的例子:吃飯這個動作相當(dāng)于切點(diǎn),我們可以在這個切點(diǎn)前、后插入其它如洗手等動作。

AOP(Aspect-Oriented Programming):面向切面編程,是對 OOP 的補(bǔ)充。利用AOP可以對業(yè)務(wù)邏輯的各個部分進(jìn)行隔離,也可以隔離業(yè)務(wù)無關(guān)的功能比如日志上報、異常處理等,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高業(yè)務(wù)無關(guān)的功能的復(fù)用性,也就提高了開發(fā)的效率。

在 JavaScript 中,我們可以通過裝飾者模式來實(shí)現(xiàn) AOP,但是兩者并不是一個維度的概念。 AOP 是一種編程范式,而裝飾者是一種設(shè)計(jì)模式。

ES3 下裝飾者的實(shí)現(xiàn)

了解了裝飾者模式和 AOP 的概念之后,我們寫一段能夠兼容 ES3 的代碼來實(shí)現(xiàn)裝飾者模式:

// 原函數(shù)
var takePhoto =function(){
    console.log("拍照片");
}
// 定義 aop 函數(shù)
var after=function( fn, afterfn ){ 
    return function(){
        let res = fn.apply( this, arguments ); 
        afterfn.apply( this, arguments );
        return res;
    }
}
// 裝飾函數(shù)
var addFilter=function(){
    console.log("加濾鏡");
}
// 用裝飾函數(shù)裝飾原函數(shù)
takePhoto=after(takePhoto,addFilter);

takePhoto();

這樣我們就實(shí)現(xiàn)了抽離拍照與濾鏡邏輯,如果以后需要自動上傳功能,也可以通過aop函數(shù)after來添加。

ES5 下裝飾者的實(shí)現(xiàn)

在 ES5 中引入了Object.defineProperty,我們可以更方便的給對象添加屬性:

let takePhoto = function () {
    console.log("拍照片");
}
// 給 takePhoto 添加屬性 after
Object.defineProperty(takePhoto, "after", {
    writable: true,
    value: function () {
        console.log("加濾鏡");
    },
});
// 給 takePhoto 添加屬性 before
Object.defineProperty(takePhoto, "before", {
    writable: true,
    value: function () {
        console.log("打開相機(jī)");
    },
});
// 包裝方法
let aop = function (fn) {
    return function () {
        fn.before()
        fn()
        fn.after()
    }
}

takePhoto = aop(takePhoto)
takePhoto()
基于原型鏈和類的裝飾者實(shí)現(xiàn)

我們知道,在 JavaScript 中,函數(shù)也好,類也好都有著自己的原型,通過原型鏈我們也能夠很方便的動態(tài)擴(kuò)展,以下是基于原型鏈的寫法:

class Test {
    takePhoto() {
        console.log("拍照");
    }
}
// after AOP
function after(target, action, fn) {
    let old = target.prototype[action];
    if (old) {
        target.prototype[action] = function () {
            let self = this;
            fn.bind(self);
            fn(handle);
        }
    }
}
// 用 AOP 函數(shù)修飾原函數(shù)
after(Test, "takePhoto", () => {
    console.log("添加濾鏡");
});

let t = new Test();
t.takePhoto();
使用 ES7 修飾器實(shí)現(xiàn)裝飾者

在 ES7 中引入了@decorator 修飾器的提案,參考阮一峰的文章)。修飾器是一個函數(shù),用來修改類的行為。目前Babel轉(zhuǎn)碼器已經(jīng)支持。注意修飾器只能裝飾類或者類屬性、方法。三者的具體區(qū)別請參考 MDN Object.defineProperty ;而 TypeScript 的實(shí)現(xiàn)又有所不同:TypeScript Decorator。

接下來我們通過修飾器來實(shí)現(xiàn)對方法的裝飾:

function after(target, key, desc) {
    const { value } = desc;
    desc.value = function (...args) {
        let res = value.apply(this, args);
        console.log("加濾鏡")
        return res;
    }
    return desc;
}

class Test{
    @after
    takePhoto(){
        console.log("拍照")
    }
}

let t = new Test()
t.takePhoto()

可以看到,使用修飾器的代碼非常簡潔明了。

場景:性能上報

裝飾者模式可以應(yīng)用在很多場景,典型的場景是記錄某異步請求請求耗時的性能數(shù)據(jù)并上報:

function report(target, key, desc) {
    const { value } = desc;
    desc.value = async function (...args) {
        let start = Date.now();
        let res = await value.apply(this, args);
        let millis = Date.now()-start;
        // 上報代碼
        return res;
    }
    return desc;
}

class Test{
    @report
    getData(url){
    // fetch 代碼
    }
}

let t = new Test()
t.getData()

這樣使用@report修飾后的代碼就會上報請求所消耗的時間。擴(kuò)展或者修改report函數(shù)不會影響業(yè)務(wù)代碼,反之亦然。

場景:異常處理

我們可以對原有代碼進(jìn)行簡單的異常處理,而無需侵入式的修改:

function handleError(target, key, desc) {
    const { value } = desc;
    desc.value = async function (...args) {
        let res;
        try{
            res = await value.apply(this, args);
        }catch(err){
            // 異常處理
            logger.error(err)
        }
        return res;
    }
    return desc;
}

class Test{
    @handleError
    getData(url){
        // fetch 代碼
    }
}

let t = new Test()
t.getData()

通過以上兩個示例我們可以看到,修飾器的定義很簡單,功能卻非常強(qiáng)大。

小結(jié)

我們一步一步通過高階函數(shù)、原型鏈、Object.defineProperty@Decorator分別實(shí)現(xiàn)了裝飾者模式。接下來在回顧一下:

裝飾者模式非常適合給業(yè)務(wù)代碼附加非業(yè)務(wù)相關(guān)功能(如日志上報),就如同給照片加濾鏡;

裝飾者模式非常適合無痛擴(kuò)展別人的代碼(你經(jīng)常需要接手別人的項(xiàng)目吧)

有些朋友可能會覺得裝飾者模式和 vue 的 mixin 機(jī)制很像,其實(shí)他們都是“開放-封閉原則”和“單一職責(zé)原則”的體現(xiàn)。

附上代碼 jsbin 地址:

ES3

ES5

原型鏈

ES7

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

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/104942.html

相關(guān)文章

  • javascript設(shè)計(jì)模式--裝飾模式

    摘要:裝飾者模式定義裝飾者模式能夠在不改變對象自身的基礎(chǔ)上,在程序運(yùn)行期間給對像動態(tài)的添加職責(zé)。與繼承相比,裝飾者是一種更輕便靈活的做法。 裝飾者模式 定義 : 裝飾者(decorator)模式能夠在不改變對象自身的基礎(chǔ)上,在程序運(yùn)行期間給對像動態(tài)的添加職責(zé)。與繼承相比,裝飾者是一種更輕便靈活的做法。 在不改變對象自身的基礎(chǔ)上,在程序運(yùn)行期間給對象動態(tài)地添加一些額外職責(zé) 特點(diǎn) : 可以動態(tài)的...

    haoguo 評論0 收藏0
  • JavaScript裝飾模式

    摘要:用戶名不能為空密碼不能為空校驗(yàn)未通過使用優(yōu)化代碼返回的情況直接,不再執(zhí)行后面的原函數(shù)用戶名不能為空密碼不能為空 本文是《JavaScript設(shè)計(jì)模式與開發(fā)實(shí)踐》的學(xué)習(xí)筆記,例子來源于書中,對于設(shè)計(jì)模式的看法,推薦看看本書作者的建議。 什么是裝飾者模式? 給對象動態(tài)增加職責(zé)的方式成為裝飾者模式。 裝飾者模式能夠在不改變對象自身的基礎(chǔ)上,在運(yùn)行程序期間給對象動態(tài)地添加職責(zé)。這是一種輕便靈活...

    Taste 評論0 收藏0
  • 面試官:“談?wù)凷pring中都用到了那些設(shè)計(jì)模式?”。

    摘要:會一直完善下去,歡迎建議和指導(dǎo),同時也歡迎中用到了那些設(shè)計(jì)模式中用到了那些設(shè)計(jì)模式這兩個問題,在面試中比較常見。工廠設(shè)計(jì)模式使用工廠模式可以通過或創(chuàng)建對象。 我自己總結(jié)的Java學(xué)習(xí)的系統(tǒng)知識點(diǎn)以及面試問題,已經(jīng)開源,目前已經(jīng) 41k+ Star。會一直完善下去,歡迎建議和指導(dǎo),同時也歡迎Star: https://github.com/Snailclimb... JDK 中用到了那...

    Astrian 評論0 收藏0
  • 學(xué)學(xué)AOP裝飾模式

    摘要:但是,這樣做的后果就是,我們會不斷的改變本體,就像把鳳姐送去做整形手術(shù)一樣。在中,我們叫做引用裝飾。所以,這里引入的裝飾模式裝飾親切,熟悉,完美。實(shí)例講解裝飾上面那個例子,只能算是裝飾模式的一個不起眼的角落。 裝飾者,英文名叫decorator. 所謂的裝飾,從字面可以很容易的理解出,就是給 土肥圓,化個妝,華麗的轉(zhuǎn)身為白富美,但本體還是土肥圓。 說人話.咳咳~ 在js里面一切都是對...

    nihao 評論0 收藏0
  • javascript設(shè)計(jì)模式 --- 裝飾模式

    摘要:設(shè)計(jì)模式裝飾者模式何為裝飾者,意思就是,在不影響對象主功能的情況下,再添加一些額外的功能,使對象具備更多的功能。與繼承相比,裝飾者是一種更靈活輕便的做法。 javascript設(shè)計(jì)模式 --- 裝飾者模式 何為裝飾者,意思就是,在不影響對象主功能的情況下,再添加一些額外的功能,使對象具備更多的功能。與繼承相比,裝飾者是一種更靈活輕便的做法。下面我們看看javascript里裝飾者模式 ...

    kumfo 評論0 收藏0

發(fā)表評論

0條評論

chunquedong

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<