亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

javascript設計模式--裝飾者模式

haoguo / 2299人閱讀

摘要:裝飾者模式定義裝飾者模式能夠在不改變對象自身的基礎上,在程序運行期間給對像動態(tài)的添加職責。與繼承相比,裝飾者是一種更輕便靈活的做法。

裝飾者模式 定義 :

裝飾者(decorator)模式能夠在不改變對象自身的基礎上,在程序運行期間給對像動態(tài)的添加職責。與繼承相比,裝飾者是一種更輕便靈活的做法。

在不改變對象自身的基礎上,在程序運行期間給對象動態(tài)地添加一些額外職責

特點 :

可以動態(tài)的給某個對象添加額外的職責,而不會影響從這個類中派生的其它對象;

作用:

裝飾者模式的作用就是為對象動態(tài)的加入某些行為。

為什么要使用裝飾者模式

在傳統(tǒng)面向?qū)ο笳Z言中,為對象添加功能常使用繼承
但是繼承有很多缺點:

超類子類強耦合,超類改變導致子類改變
超類內(nèi)部細節(jié)對子類可見,破壞了封裝性
完成功能復用同時,可能會創(chuàng)造大量子類

舉例:

var person = {
    name: "payen",
    sex: "male"
}
person.age = "20";

裝飾者模式是在不改變對象自身的基礎上
而我們改變了原對象 ,所以上面這個例子不是裝飾器

示例:
/*模擬傳統(tǒng)語言的裝飾者
 裝飾者模式將一個對象嵌入到另一個對象之中,
實際上相當于這個對象被另一個對像包裝起來,形成一條包裝鏈。
請求隨著這條包裝鏈依次傳遞到所有的對象,每個對象都有處理這條請求的機會。
*/

//原始的飛機類
var Plan = function () {
};

Plan.prototype.fire = function () {
    console.log("發(fā)射普通子彈");
};


//裝飾類
var MissileDecorator = function (plan) {
    this.plan = plan;
};

MissileDecorator.prototype.fire = function () {
    this.plan.fire();
    console.log("發(fā)射導彈!");
};

var plan = new Plan();
plan = new MissileDecorator(plan);
plan.fire();

這樣給對象動態(tài)的增加職責的方式就沒有改變對象自身
一個對象放入另一個對象
形成了一條裝飾鏈(一個聚合對象)
而上面的shot和track也就是是裝飾者、裝飾函數(shù)
當函數(shù)執(zhí)行時,會把請求轉(zhuǎn)給鏈中的下一個對象

函數(shù)功能擴展

在JavaScript中,很容易給對象擴展屬性與方法
但是卻不容易給函數(shù)擴展額外功能,除非改函數(shù)源碼
但是改寫函數(shù)違反了開放-封閉原則

var foo = function(){
    console.log(1);
}
//改為
var foo = function(){
    console.log(1);
    console.log(2);//增
}

一個常用的方法就是緩存函數(shù)引用,改寫函數(shù)

var foo = function(){
    console.log(1);
}
//改為
var foo = function(){
    console.log(1);
}
var _foo = foo;
foo = function(){
    _foo();
    console.log(2);
}

但是這樣寫還是存在問題

*要維護額外的中間變量(_foo),如果裝飾鏈過長,中間變量就會越來越多
可能會存在this被劫持問題*
關于this劫持問題,看下面的例子:

var getId = document.getElementById;
document.getElementById = function(ID){
    console.log(1);
    return getId(ID);
}
document.getElementById("demo");

因為使用 document.getElementById 的時候
內(nèi)部有this引用,而這個this期望指向的是document
但是 getId 在獲取了 document.getElementById 引用后
this就指向了window,導致拋出錯誤

為了讓this正確指向document
我們可以做出修改:

    var getId = document.getElementById;
document.getElementById = function(ID){
    console.log(1);
    return getId.call(document, ID);
}
document.getElementById("demo");
AOP裝飾函數(shù)

AOP(Aspect Oriented Programming)面向切面編程
把一些與核心業(yè)務邏輯無關的功能抽離出來
再通過“動態(tài)織入”方式摻入業(yè)務邏輯模塊

與業(yè)務邏輯無關的功能通常包括日志統(tǒng)計、安全控制、異常處理等等
好處也很明顯,保證了核心業(yè)務模塊的純凈與高內(nèi)聚性
而且其他的功能模塊也可以很好的復用
首先我們要實現(xiàn)兩個函數(shù)
一個用來前置裝飾,一個用來后置裝飾:

Function.prototype.before = function(beforeFunc){
    var that = this;
    return function(){
        beforeFunc.apply(this, arguments);
        return that.apply(this, arguments);
    }
}
Function.prototype.after = function(afterFunc){
    var that = this;
    return function(){
        var ret = that.apply(this, arguments);
        afterFunc.apply(this, arguments);
        return ret;
    }
}

以前置裝飾為例
調(diào)用before時,先把原函數(shù)的引用保存下來
然后返回一個“代理”函數(shù)
這樣在原函數(shù)調(diào)用前,先執(zhí)行擴展功能的函數(shù)
而且他們共用同一個參數(shù)列表
后置裝飾與前置裝飾基本類似,只是執(zhí)行順序不同

如果不喜歡這種污染原型的方式,也可以這么寫:

var before = function(originFunc, beforeFunc){
    return function(){
        before.apply(this, arguments);
        return originFunc.apply(this, arguments);
    }
}
var after = function(originFunc, afterFunc){
    return function(){
        var ret = originFunc.apply(this, arguments);
        afterFunc.apply(this, arguments);
        return ret;
    }
}

使用這種AOP的方式可以完美的對函數(shù)進行功能擴展

var foobar = function(x, y, z){
    console.log(x, y, z);
}
var foo = function(x, y, z){
    console.log(x/10, y/10, z/10);
}
var bar = function(x, y, z){
    console.log(x*10, y*10, z*10);
}
foobar = foobar.before(foo).after(bar);
foobar(1, 2, 3);
//0.1 0.2 0.3
//1 2 3
//10 20 30

由于原函數(shù)和裝飾函數(shù)共用一個參數(shù)列表
所以我們可以用AOP改變函數(shù)參數(shù)

var data = {
    width: "100px",
    height: "100px"
}
var demo = function(data){
    console.log(JSON.stringify(data));
}
demo = demo.before(function(data){
    data.color = "red";
});
demo(data);
//{"width":"100px","height":"100px","color":"red"}

最后談一談裝飾者模式的缺點
它也不是十全十美的

裝飾鏈疊加了函數(shù)作用域,如果過長也會產(chǎn)生性能問題
如果原函數(shù)上保存了屬性,返回新函數(shù)后屬性會丟失

var demo = function(){
    console.log(1);
}
demo.a = 123;
demo = demo.after(function(){
    console.log(2);
});
demo();
console.log(demo.a);
//undefined

裝飾者模式在開發(fā)中非常有用,在框架開發(fā)中也十分有用

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

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/88798.html

相關文章

  • JavaScript設計模式----裝飾模式

    摘要:聲明這個系列為閱讀設計模式與開發(fā)實踐曾探著一書的讀書筆記裝飾者模式的定義裝飾者模式能夠在不改變對象自身的基礎上,在程序運行期間給對像動態(tài)的添加職責。與繼承相比,裝飾者是一種更輕便靈活的做法。裝飾者模式的作用就是為對象動態(tài)的加入某些行為。 聲明:這個系列為閱讀《JavaScript設計模式與開發(fā)實踐》 ----曾探@著一書的讀書筆記 裝飾者模式的定義: 裝飾者(decorator)模式能...

    rose 評論0 收藏0
  • 5 分鐘即可掌握的 JavaScript 裝飾模式與 AOP

    摘要:下裝飾者的實現(xiàn)了解了裝飾者模式和的概念之后,我們寫一段能夠兼容的代碼來實現(xiàn)裝飾者模式原函數(shù)拍照片定義函數(shù)裝飾函數(shù)加濾鏡用裝飾函數(shù)裝飾原函數(shù)這樣我們就實現(xiàn)了抽離拍照與濾鏡邏輯,如果以后需要自動上傳功能,也可以通過函數(shù)來添加。 showImg(https://segmentfault.com/img/bVbueyz?w=852&h=356); 什么是裝飾者模式 當我們拍了一張照片準備發(fā)朋友...

    chunquedong 評論0 收藏0
  • javascript設計模式 --- 裝飾模式

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

    kumfo 評論0 收藏0
  • JavaScript設計模式七:裝飾模式

    摘要:裝飾者模式裝飾者模式提供比繼承更有彈性的替代方案。裝飾者用于包裝同接口的對象,用于通過重載方法的形式添加新功能,該模式可以在被裝飾者的前面或后面加上自己的行為以達到特定的目的。簡單的理解給對象動態(tài)添加職責的方式稱為裝飾著模式。 裝飾者模式 裝飾者模式提供比繼承更有彈性的替代方案。裝飾者用于包裝同接口的對象,用于通過重載方法的形式添加新功能,該模式可以在被裝飾者的前面或后面加上自己的行為...

    alexnevsky 評論0 收藏0
  • JavaScript 模式》知識點小抄本(上)

    摘要:單體模式有以下優(yōu)點用來劃分命名空間,減少全局變量數(shù)量。通常我們使用操作符創(chuàng)建單體模式的三種選擇,讓構造函數(shù)總返回最初的對象使用全局對象來存儲該實例不推薦,容易全局污染。實現(xiàn)該工廠模式并不困難,主要是要找到能夠穿件所需類型對象的構造函數(shù)。 介紹 最近開始給自己每周訂個學習任務,學習結果反饋為一篇文章的輸出,做好學習記錄。 這一周(02.25-03.03)我定的目標是《JavaScri...

    didikee 評論0 收藏0

發(fā)表評論

0條評論

haoguo

|高級講師

TA的文章

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