裝飾者模式【javascript設計模式】

其實生命就是這樣呻畸,從無到有移盆,從稚嫩到成熟。現狀態(tài)轉變自前一個狀態(tài)伤为,只是多了點東西味滞,它們就變得相互獨立,形同陌路钮呀。

裝飾者模式剑鞍,聽名字就會明白,是在原有對象的基礎上爽醋,給其裝飾一些東西蚁署,使其成為一個新的對象。舉個例子:我現在是一個單身狗蚂四,給我一個女朋友光戈,我就變成了有女朋友的單身狗;換句話說就是遂赠,我現在是一個單身狗對象久妆,給我裝飾了一個女朋友,我就成為一個有女朋友的單身狗對象跷睦。接下來用代碼闡述一下:

const SingleDog = function () {

}

SingleDog.prototype.say = function () {
    console.log('我是一只單身狗');
}

const DecorateGfriend = function (men) {
    this.men = men;
}

DecorateGfriend.prototype.say = function () {
    this.men.say();
    console.log('我有女朋友');
}

const me = new DecorateGfriend(new SingleDog());

me.say(); // 我是一只單身狗筷弦,我有女朋友

OK,我們先來看一下上面的代碼抑诸,至關重要的DecorateGfriend做了二件事情:1. 調用了SingleDog的say函數星掰;2. 額外打印出了一句話橘蜜。這兩點其實就是裝飾者模式的精髓:在保持原有對象功能的基礎上,增加新功能
上面的代碼看起來不太好看组题,又多又亂而且DecorateGfriend似乎違反了開放-封閉原則维蒙,即我要是想秀波恩愛陪踩,額外打印出一句“我很幸附缧”之類云云萝招,需要直接改DecorateGfriend的代碼,這樣子是不行的辛块,所以有沒有什么好的方法嘞畔派?下面給出 2 個經典的AOP裝飾函數:

Function.prototype.before = function(beforefn) {
    const self = this;
    return function () {
        beforefn.apply(this, arguments);
        return self.apply(this, arguments);
    }
}

Function.prototype.after = function(afterfn) {
    const self = this;

    return function () {
        const ret = self.apply(this, arguments);
        afterfn.apply(this, arguments);
        return ret;
    }
}

來看看第一個函數,正如上面提到的憨降,做了兩件事情:1. 先調用了傳遞進來的函數父虑,2. 在調用了函數本身该酗。第二個函數和上面相反授药。所以士嚎,我們可以用上面的函數來重構單身狗的例子:

Function.prototype.after = function(afterfn) {
    const self = this;

    return function () {
        const ret = self.apply(this, arguments);
        afterfn.apply(this, arguments);
        return ret;
    }
}

const singleDogSay = function () {
    console.log('我是一只單身狗');
}

const decorateGfriend = function () {
    console.log('我裝飾了一個女朋友');
}

const flaunt = function () {
    console.log('秀死你們');
}

const me = singleDogSay.after(decorateGfriend).after(flaunt);

me(); // 我是一只單身狗 我裝飾了一個女朋友 秀死你們

是不是很爽,想秀多少波都可以悔叽,只要一直after下去莱衩。


接下來,我們來思考一個問題娇澎,裝飾者模式能給我們日常的開發(fā)中帶來哪些好處呢笨蚁?

可以把行為依照職責分成更細的粒度,隨后將它們合并到一起趟庄,這有助于我們編寫一個松耦合高復用的系統(tǒng)

下面是兩個啟發(fā)性例子:

1括细、

大家或許都接觸過“埋點”,一種統(tǒng)計的方式戚啥。比如想獲取有多少用戶點擊了這個活動的按鈕奋单,會在這個按鈕點擊時發(fā)送一條統(tǒng)計數據到服務器。
按照正常思維大家會寫這樣的代碼:

const btn = document.getElementById('J_btn');

const doSomething = function() {
    console.log('用戶點擊這個按鈕后發(fā)生的事情');
}

const sendInfo = function() {
    console.log('發(fā)送埋點信息');
}

btn.onClick = function() {
    doSomething();
    sendInfo();
}

上面這段代碼違反了單一職責原則猫十,這個按鈕要做的事情僅僅是doSomething里面的览濒,但是它不得不在onClick實踐中又執(zhí)行了發(fā)送埋點信息這一個操作。所以拖云,我們需要將它贷笛, 分開,而裝飾者模式正好為我們提供了完美的解決方案:

Function.prototype.after = function(afterfn) {
    const self = this;

    return function () {
        const ret = self.apply(this, arguments);
        afterfn.apply(this, arguments);
        return ret;
    }
}

const btn = document.getElementById('J_btn');

let doSomething = function() {
    console.log('用戶點擊這個按鈕后發(fā)生的事情');
}

const sendInfo = function() {
    console.log('發(fā)送埋點信息');
}

doSomething = doSomething.after(sendInfo);

btn.onClick = doSomething;

這樣就很清晰了宙项,按鈕點擊后只是執(zhí)行doSomthing里面的內容乏苦,而埋點只不過是“附帶”執(zhí)行的操作,在代碼可讀性方面一目了然尤筐,而且兩個函數各自的修改并不會對其他函數造成影響邑贴,完美符合單一職責原則。

2叔磷、

表單驗證
大家應該都編寫過表單驗證的程序:在用戶填寫好一堆表單數據后拢驾,在上傳至服務器前要對表單數據進行校驗,比如改基,用戶名密碼是否為空之類繁疤。遇到這種情況,很直觀的思路是寫下面這樣的代碼實現:

const name = document.getElementById('name');
const password = document.getElementById('password');
const submit = document.getElementById('submit');

submit.onClick = function() {
    if (name === '') {
        console.log('用戶名不能為空');
        return;
    }
    if (password === '') {
        console.log('密碼不能為空');
        return;
    }

里面校驗的邏輯可以抽出來秕狰,所以變成這樣:

const name = document.getElementById('name');
const password = document.getElementById('password');
const submit = document.getElementById('submit');

const validate = function () {
    if (name === '') {
        console.log('用戶名不能為空');
        return false;
    }
    if (password === '') {
        console.log('密碼不能為空');
        return false;
    }
    return ture;
}

submit.onClick = function() {
    if (!validate()) return;
    console.log('開始上傳');
}

但是同樣違反了單一職責原則稠腊,上傳只做上傳的事情就OK,不應該參雜校驗的邏輯鸣哀,我們可以用裝飾者模式改寫如下:

const name = document.getElementById('name');
const password = document.getElementById('password');
const submit = document.getElementById('submit');

Function.prototype.before = function(beforefn) {
    const self = this;

    return function () {
        if (!beforefn.apply(this, arguments)) {
            return;
        }
        return self.apply(this, arguments);
    }
}

const validate = function () {
    if (name === '') {
        console.log('用戶名不能為空');
        return false;
    }
    if (password === '') {
        console.log('密碼不能為空');
        return false;
    }

    return ture;
}

let forSubmit = function () {
    console.log('開始上傳');
}

submit.onClick = forSubmit.before(validate);;

咋們稍稍改了一下before函數架忌,使其前面執(zhí)行的函數返回為false時不執(zhí)行后面的函數。用裝飾者模式重構一波后我衬,是不是感覺很清爽叹放。饰恕。。


最后打兩個廣告:
酷家樂內推歡迎找我井仰,郵箱:chonger@qunhemail.com
單身妹子歡迎找我埋嵌,微信:mz975066610^?_?^

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市俱恶,隨后出現的幾起案子雹嗦,更是在濱河造成了極大的恐慌,老刑警劉巖合是,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件了罪,死亡現場離奇詭異,居然都是意外死亡聪全,警方通過查閱死者的電腦和手機捶惜,發(fā)現死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荔烧,“玉大人吱七,你說我怎么就攤上這事『捉撸” “怎么了踊餐?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長臀稚。 經常有香客問我吝岭,道長,這世上最難降的妖魔是什么吧寺? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任窜管,我火速辦了婚禮,結果婚禮上稚机,老公的妹妹穿的比我還像新娘幕帆。我一直安慰自己,他們只是感情好赖条,可當我...
    茶點故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布失乾。 她就那樣靜靜地躺著,像睡著了一般纬乍。 火紅的嫁衣襯著肌膚如雪碱茁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天仿贬,我揣著相機與錄音纽竣,去河邊找鬼。 笑死,一個胖子當著我的面吹牛蜓氨,可吹牛的內容都是我干的聋袋。 我是一名探鬼主播,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼语盈,長吁一口氣:“原來是場噩夢啊……” “哼舱馅!你這毒婦竟也來了缰泡?” 一聲冷哼從身側響起刀荒,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎棘钞,沒想到半個月后缠借,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡宜猜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年泼返,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片姨拥。...
    茶點故事閱讀 38,664評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡绅喉,死狀恐怖,靈堂內的尸體忽然破棺而出叫乌,到底是詐尸還是另有隱情柴罐,我是刑警寧澤,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布憨奸,位于F島的核電站革屠,受9級特大地震影響,放射性物質發(fā)生泄漏排宰。R本人自食惡果不足惜似芝,卻給世界環(huán)境...
    茶點故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望板甘。 院中可真熱鬧党瓮,春花似錦、人聲如沸盐类。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽傲醉。三九已至蝇闭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間硬毕,已是汗流浹背呻引。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留吐咳,地道東北人逻悠。 一個月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓元践,卻偏偏與公主長得像,于是被迫代替她去往敵國和親童谒。 傳聞我的和親對象是個殘疾皇子单旁,可洞房花燭夜當晚...
    茶點故事閱讀 43,554評論 2 349

推薦閱讀更多精彩內容

  • 工廠模式類似于現實生活中的工廠可以產生大量相似的商品,去做同樣的事情饥伊,實現同樣的效果;這時候需要使用工廠模式象浑。簡單...
    舟漁行舟閱讀 7,726評論 2 17
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,795評論 25 707
  • 接觸前端兩三個月的時候,那時候只是聽說設計模式很重要琅豆,然后我就去讀了一本設計模式的書愉豺,讀了一部分,也不知道這些設計...
    艱苦奮斗的侯小憨閱讀 3,033評論 2 39
  • 很久很久以前 在高樓出現之前 在宮殿出現之前 在神話出現之前 有一個人 他捧起一把落葉 感嘆道 秋天來了
    Arabian_Nights閱讀 236評論 0 0
  • 啊茫因,看名偵探柯南的時候蚪拦,還是我小學的時候,那時候個連續(xù)劇冻押,如今慢慢的改編成了電影驰贷。 怎么說呢,這部電影一樣的配方洛巢,...
    因為我太傻啊閱讀 490評論 0 0