1.什么是装饰器模式
Decorator Design Pattern:
当我们拍了一张照片准备发朋友圈时,我们会选择给照片加上滤镜。同一张照片、不同的滤镜组合起来就会有不同的体验。这实际上就是装饰者模式:是通过滤镜装饰了照片。在不改变对象(照片)的情况下,动态的为其添加功能(滤镜),而且通过不同的装饰器组合(不同的滤镜组合),可以达到叠加的效果。
需要注意的是:由于 JavaScript 语言动态的特性,我们很容易就能改变某个对象。但是我们要尽量避免直接改写某个函数,这违反了开闭原则。js里函数也是对象因此js中的装饰器模式,实际上是装饰的是函数。
2.使用AOP装饰函数
回到上面的例子,因为装饰的是函数,因此改为给拍照片这个动作(而不是照片)添加滤镜功能。
// AOP函数const after = function(fn, afterFn) {return function (...args) {const ret = fn.apply(this, args);afterFn.apply(this, args);return ret;}}// 原函数const takePhoto = function(){console.log('拍照片');}// 装饰函数const addFilter = function(){console.log('添加滤镜');}takePhoto = after(takePhoto, addFilter);takePhoto();
3.基于类的原型对象装饰类里的方法
/**** @param {*} target 类* @param {*} action 类里的方法名* @param {*} afterFn 装饰函数*/function after(target, action, afterFn) {oldAction = target.prototype[action];if (oldAction) {target.prototype[action] = function (...args) {const ret = oldAction.apply(this, args);afterFn.apply(this, args);return ret;}}}class PhotoUtils {takePhoto() {console.log('拍照片');}}function addFilter() {console.log('添加滤镜')}const pu = new PhotoUtils();after(PhotoUtils, 'takePhoto', addFilter);pu.takePhoto();
4.ES和TS中的装饰器
目前Decorator在语言里还处于提案阶段,想用但不敢用啊
参考文献
https://mp.weixin.qq.com/s/WcoX4H4LLgyvr8ELxcE6FQ
《JavaScript设计模式和开发实践》
