在《設計模式》成書以前,GoF 原想把裝 飾者(decorator)模式稱爲包裝器(wrapper) 模式。從功能上而言,decorator能很好地描述這個模式,但從結構上看,wrapper的說法更加 貼切。裝飾者模式將一個對象嵌入另外一個對象之中,實際上至關於這個對象被另外一個對象包 裝起來,造成一條包裝鏈。請求隨着這條鏈依次傳遞到全部的對象,每一個對象都有處理這條 請求的機會。 使用場景像數據上報, 日誌記錄等。設計模式
保證原來代碼不變的同時增長新功能bash
function log1() {
console.log(1);
}
const _log1 = log1;
log1 = function() {
_log1();
console.log(2); // 新增的功能
}
複製代碼
新增功能 卻不要改變log1 的源代碼, 保存源代碼的引用, 使用裝飾的模式新增功能app
Function.prototype.before = function(beforeFn) {
const self = this; // 保存原函數的引用
return function(...args) {
beforeFn.apply(this, args);
return self.apply(this, args);
}
}
Function.prototype.after = function (afterFn) {
const self = this;
return function(...args) {
const ret = self.apply(this, args);
afterFn.apply(this, args);
return ret;
}
}
window.onload = () => {
console.log('onload', 1);
}
window.onload = (window.onload || (() => {})).after(() => { console.log(2) }).after(() => { console.log(3) }).before(() => { console.log('before')});
// => before, onload 1, 2, 3
複製代碼
這裏有個問題, before 和after 執行的時候是 return 一個函數, 那這個函數是何時執行的呢, 誰調用了呢。這個沒想明白函數
裝飾者模式和代理模式的結構看起來很是相像,這兩種模式都描述了怎樣爲對象提供 必定程度上的間接引用,它們的實現部分都保留了對另一個對象的引用,而且向那個對象發送請求。 代理模式和裝飾者模式最重要的區別在於它們的意圖和設計目的。代理模式的目的是,當直 接訪問本體不方便或者不符合須要時,爲這個本體提供一個替代者。本體定義了關鍵功能,而代 理提供或拒絕對它的訪問,或者在訪問本體以前作一些額外的事情。裝飾者模式的做用就是爲對象動態加入行爲。換句話說,代理模式強調一種關係(Proxy與它的實體之間的關係),這種關係能夠靜態的表達,也就是說,這種關係在一開始就能夠被肯定。而裝飾者模式用於一開始不能肯定對象的所有功能時。代理模式一般只有一層代理本體的引用,而裝飾者模式常常會造成一條 長長的裝飾鏈。ui