定义
在《设计模式》成书之前,GoF 原想把装 饰者(decorator)模式称为包装器(wrapper) 模式。从功能上而言,decorator能很好地描述这个模式,但从结构上看,wrapper的说法更加 贴切。装饰者模式将一个对象嵌入另一个对象之中,实际上相当于这个对象被另一个对象包 装起来,形成一条包装链。请求随着这条链依次传递到所有的对象,每个对象都有处理这条 请求的机会。 使用场景像数据上报, 日志记录等。
12.1 引入装饰器
保证原来代码不变的同时增加新功能
function log1() {
console.log(1);
}
const _log1 = log1;
log1 = function() {
_log1();
console.log(2); // 新增的功能
}
复制代码
新增功能 却不要改变log1 的源代码, 保存源代码的引用, 使用装饰的模式新增功能
12.2 使用AOP实现装饰器模式
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 一个函数, 那这个函数是什么时候执行的呢, 谁调用了呢。这个没想明白
12.3 总结
装饰者模式和代理模式的结构看起来非常相像,这两种模式都描述了怎样为对象提供 一定程度上的间接引用,它们的实现部分都保留了对另外一个对象的引用,并且向那个对象发送请求。 代理模式和装饰者模式最重要的区别在于它们的意图和设计目的。代理模式的目的是,当直 接访问本体不方便或者不符合需要时,为这个本体提供一个替代者。本体定义了关键功能,而代 理提供或拒绝对它的访问,或者在访问本体之前做一些额外的事情。装饰者模式的作用就是为对象动态加入行为。换句话说,代理模式强调一种关系(Proxy与它的实体之间的关系),这种关系可以静态的表达,也就是说,这种关系在一开始就可以被确定。而装饰者模式用于一开始不能确定对象的全部功能时。代理模式通常只有一层代理本体的引用,而装饰者模式经常会形成一条 长长的装饰链。