這是我參與更文挑戰的第3天,活動詳情查看: 更文挑戰javascript
大佬們輕噴~我是標題黨(狗頭保命)java
簡單來講,裝飾器模式就是給對象動態增長功能。git
有一個鴨子對象,它會發聲 makeVoice
, 會睡覺 sleep
,可是由於它還過小,不會走路,代碼以下:github
const duck = {
makeVoice: () => {
console.log('我會嘎嘎嘎啦')
},
sleep: () => {
console.log('誰又不會睡覺呢')
},
init: function () {
this.makeVoice()
this.sleep()
}
}
duck.init()
複製代碼
當它 3 個月大的時候,忽然學會走路 walk
了,這個時候,怎麼在代碼中,爲鴨子 duck
添加走路 walk
功能呢?大多數狀況下,咱們會選擇直接修改鴨子 duck
方法,代碼以下:web
const duck = {
makeVoice: () => {
console.log('我會嘎嘎嘎啦')
},
sleep: () => {
console.log('誰又不會睡覺呢')
},
walk: () => {
console.log('哈哈哈,我會走路啦')
},
init: function () {
this.makeVoice()
this.sleep()
this.walk()
}
}
duck.init()
複製代碼
快樂的時光老是短暫的,鴨子越長越大,功能也愈來愈多。有一天,你請假出去玩,拜託朋友幫你照顧這隻鴨子,不巧,鴨子要下蛋了,朋友須要幫鴨子添加一個下蛋的功能,這就有點麻煩了由於這是他第一次照顧這隻鴨子,他擔憂若是直接在鴨子內部添加方法會影響到什麼。ajax
因而他想到了一個好方法,不直接修改鴨子內部,而是經過一個外部函數,引用這個鴨子,併爲外部函數添加下蛋的功能。編程
代碼以下:設計模式
const before = function (fn, beforeFn) {
return function () {
beforeFn.apply(this, arguments)
return fn.apply(this, arguments)
}
}
const after = function (fn, afterFn) {
return function () {
const __ = fn.apply(this, arguments)
afterFn.apply(this, arguments)
return __
}
}
const duck = {
makeVoice: function () {
console.log('我會嘎嘎嘎啦')
},
sleep: function () {
console.log('誰又不會睡覺呢')
},
walk: function () {
console.log('哈哈哈,我會走路啦')
},
init: function () {
this.makeVoice()
this.sleep()
this.walk()
}
}
after(duck.init, function egg () {
console.log('生蛋快樂~')
}).apply(duck)
複製代碼
這就是裝飾器模式,動態的爲鴨子添加功能,而不直接修改鴨子自己。markdown
自定義事件的數據上報通常都依賴於點擊事件,那麼這個點擊事件既要承擔本來的功能,又要承擔數據上報的功能。app
先上代碼:
const loginBtnClick = () => {
console.log('去登陸')
console.log('去上報')
}
複製代碼
好像沒毛病,這樣的代碼中項目中隨處可見,逃避(面向過程編程)雖可恥但有用。
能夠經過裝飾器模式來重構上述代碼,將職責劃分更細,代碼鬆耦合,可複用性更高。
const after = function (fn, afterFn) {
return function () {
const __ = fn.apply(this, arguments)
afterFn.apply(this, arguments)
return __
}
}
const showLogin = function () {
console.log('去登陸')
}
const log = function () {
console.log('去上報')
}
const loginBtnClick = after(showLogin, log)
loginBtnClick()
複製代碼
一個常規的 ajax
請求參數包括 type
/ url
/ param
,當突發一個特殊狀況,須要在 ajax
的參數中,新增一個 token
參數。
先上代碼:
const ajax = function (type, url, param) {
// 新增token參數
param.token = 'xxx'
// ...ajax請求...省略
}
複製代碼
好了,又一次違反開放-封閉原則,直接修改了 ajax
函數內部.
經過裝飾器模式,在 ajax
調用以前,爲 ajax
增長 token
參數,代碼以下:
const before = function (fn, beforeFn) {
return function () {
beforeFn.apply(this, arguments)
return fn.apply(this, arguments)
}
}
let ajax = function (type, url, param) {
console.log(arguments)
// ...ajax請求...省略
}
ajax = before(ajax, function (type, url, param) {
console.log(param)
param.token = 'xxx'
})
ajax('type', 'url', {name: 'tj'})
複製代碼
這樣作能夠減小 ajax
函數的職責,提升了 ajax
函數的可複用性,
本文經過給鴨子函數動態增長功能、數據上報、動態增長參數 3 個例子,講述了裝飾器模式的應用場景及帶給咱們的好處。
裝飾器模式,讓對象更加穩定,且易於複用。而不穩定的功能,則能夠在個性化定製時進行動態添加。
可經過 github源碼 進行實操練習。
但願本文能對你有所幫助,感謝閱讀❤️~
· 往期精彩 ·