转帖:http://taobaofed.org/blog/2015/11/16/es7-decorator/
设计模式大家都有了解,网上有很多系列教程。
这里只分享 装饰者模式 以及如何使用 ES7 的 decorator 概念。
装饰模式和适配器模式都是 包装模式 (Wrapper Pattern),它们都是通过封装其他对象达到设计的目的的,但是它们的形态有很大区别。
适配器模式我们使用的场景比较多,比如连接不同数据库的情况,你需要包装现有的模块接口,从而使之适配数据库 —— 好比你手机使用转接口来适配插座那样;
装饰模式不一样,仅仅包装现有的模块,使之 “更加华丽” ,并不会影响原有接口的功能 —— 好比你给手机添加一个外壳罢了,并不影响手机原有的通话、充电等功能;

更多区别参见:设计模式——装饰模式(Decorator)
装饰模式经典的应用是 AOP 编程,比如“日志系统”,日志系统的作用是记录系统的行为操作,它在不影响原有系统的功能的基础上增加记录环节 —— 好比你佩戴了一个智能手环,并不影响你日常的作息起居,但你现在却有了自己每天的行为记录。
更加抽象的理解,可以理解为给数据流做一层filter,因此 AOP 的典型应用包括 安全检查、缓存、调试、持久化等等。可参考Spring aop 原理及各种应用场景 。

ES7 中增加了一个 decorator 属性,它借鉴自 Python,请参考文章Decorators in ES7。
下面我们以 钢铁侠 为例讲解如何使用 ES7 的 decorator。
以钢铁侠为例,钢铁侠本质是一个人,只是“装饰”了很多武器方才变得那么 NB,不过再怎么装饰他还是一个人。

我们的示例场景是这样的
Man类,它的抵御值 2,攻击力为 3,血量为 3;
创建 Man 类:
class Man{ constructor(def = 2,atk = 3,hp = 3){ this.init(def,atk,hp); } init(def,atk,hp){ this.def = def; // 防御值 this.atk = atk; // 攻击力 this.hp = hp; // 血量 } toString(){ return `防御力:${this.def},攻击力:${this.atk},血量:${this.hp}`; } } var tony = new Man(); console.log(`当前状态 ===> ${tony}`); // 输出:当前状态 ===> 防御力:2,攻击力:3,血量:3
代码直接放在 http://babeljs.io/repl/ 中运行查看结果,记得勾选
Experimental选项和Evaluate选项
创建 decorateArmour 方法,为钢铁侠装配盔甲——注意 decorateArmour 是装饰在方法init上的。
function decorateArmour(target, key, descriptor) { const method = descriptor.value; let moreDef = 100; let ret; descriptor.value = (...args)=>{ args[0] += moreDef; ret = method.apply(target, args); return ret; } return descriptor; } class Man{ constructor(def = 2,atk = 3,hp = 3){ this.init(def,atk,hp); } @decorateArmour init(def,atk,hp){ this.def = def; // 防御值 this.atk = atk; // 攻击力 this.hp = hp; // 血量 } toString(){ return `防御力:${this.def},攻击力:${this.atk},血量:${this.hp}`; } } var tony = new Man(); console.log(`当前状态 ===> ${tony}`); // 输出:当前状态 ===> 防御力:102,攻击力:3,血量:3
我们先看输出结果,防御力的确增加了 100,看来盔甲起作用了。
初学者这里会有两个疑问:
decorateArmour方法的参数为啥是这三个?可以更换么?decorateArmour方法为什么返回的是descriptor这里给出个人的解答作为参考:
descriptor = decorator(target, key, descriptor) || descriptor; ,点到为止,这里不详细展开了,可自行看看这行代码的上下文(参考文献中也涉及到这句代码的解释)。在上面的示例中,我们成功为 普通人 增加 “盔甲” 这个装饰;现在我想再给他增加 “光束手套”,希望额外增加 50 点防御值。
Step 1:拷贝一份decorateArmour方法,改名为decorateLight,同时修改防御值的属性:
function decorateLight(target, key, descriptor) { const method = descriptor.value; let moreAtk = 50; let ret; descriptor.value = (...args)=>{ args[1] += moreAtk; ret = method.apply(target, args); return ret; } return descriptor; }
原文:http://www.cnblogs.com/abapscript/p/5023570.html