一、是什么
装饰者模式(Decorator Pattern)就是动态的给类或对象增加职责的设计模式。它能在不改变类或对象自身的基础上,在程序的运行期间动态的添加职责,跟继承相比,装饰者是一种更轻便灵活的做法
这种设计模式非常符合敏捷开发的设计思想:先提炼出产品的最小可用产品,再通过快速迭代的方式添加功能
在生活中,同一张图片,组合不同的滤镜就会有不同的体验
这里实际上就应用了装饰者模式:是通过滤镜装饰了照片。在不改变对象(照片)的情况下动态的为其添加功能(滤镜)
二、使用
在es6
上,增添了类的装饰器,用来注释或修改类和类方法,使用类的装饰器实际上就应用了装饰者模式(关于类装饰器的使用这里不再陈述)如下:
在JavaScript
中可以很方便地给某个对象扩展属性和方法,但却很难在不改动某个函数源代码的情况下,给该函数添加一些额外的功能
要想为函数添加一些功能,最简单粗暴的方式就是直接改写该函数,但这是最差的办法,直接违反了开放-封闭原则,如下:
var a = function () {
alert(1);
}
// 改成
var a = function () {
alert(1);
alert(2);
}
实际开发中,比如我们想给 window
绑定 onload
事件,但是又不确定这个事件是不是已经被其他人绑定过,为了避免覆盖掉之前的 window.onload
函数中的行为,我们一般都会先保存好原先的 window.onload
,把它放入新的 window.onload
里执行
window.onload = function () {
alert(1);
}
var _onload = window.onload || function () { };
window.onload = function () {
_onload();
alert(2);
}
同样,我们还可以使用AOP
面向切面编程来装饰函数
什么是面向切面编程?举个例子,餐前洗手、饭后漱口,吃饭这个动作相当于切点,我们可以在这个切点前、后插入其它如洗手等动作
下面则使用AOP
来修饰onLoad
:
首先定义Function.prototype.before
方法和 Function.prototype.after
方法,如下:
Function.prototype.before = function (beforefn) {
var __self = this; // 保存原函数的引用
return function () { // 返回包含了原函数和新函数的"代理"函数
beforefn.apply(this, arguments); // 执行新函数,且保证 this 不被劫持,新函数接受的参数也会被原封不动地传入原函数,新函数在原函数之前执行
return __self.apply(this, arguments); // 执行原函数并返回原函数的执行结果,并且保证 this 不被劫持
}
}
Function.prototype.after = function (afterfn) {
var __self = this;
return function () {
var ret = __self.apply(this, arguments);
afterfn.apply(this, arguments);
return ret;
}
};
Function.prototype.before
接受一个函数当作参数,这个函数即为新添加的函数,它装载了新添加的功能代码
它的工作是把请求分别转发给新添加的函数和原函数,且负责保证它们的执行顺序,让新添加的函数在原函数之前执行(前置装饰),这样就实现了动态装饰的效果。通过 Function.prototype.apply
来动态传入正确的 this
,保证了函数在被装饰之后,this
不会被劫持
Function.prototype.after
的原理跟 Function.prototype.before
一模一样,唯一不同的地方在于让新添加的函数在原函数执行之后再执行
修改后代码如下:
window.onload = function () {
alert(1);
}
window.onload = (window.onload || function () { }).after(function () {
alert(2);
}).after(function () {
alert(3);
}).after(function () {
alert(4);
});
三、总结
应用场景:
适合对已拥有必备组件的对象进行扩展高阶组件或属性
优点:
无需修改现有对象,也无需创建对象的子类,即可扩展对象的功能。
可以多扩展功能进行动态添加或删除
可以扩展不同的装饰者来解决扩展不同功能的问题
参考文献
https://juejin.cn/post/6844903873262387208
https://juejin.cn/post/6999826902642851854
https://juejin.cn/post/6844904100144889864
--The End--
系列正在更新:13/14
点击下方卡片解锁更多
创作不易,星标、点赞、在看 三连支持