装饰器的简单实现(上)
es7为javascript添加了激动人心的新特性----装饰器,不过Typrscript早就支持了装饰器了,装饰器也不是ts特有的语法,实际上python也有装饰器,在oop语言里面,一直都有装饰器模式,也称为decorator,不过都是从语言层面,通过继承和组合实现,现在,我们可以通过语法层面直接实现装饰器了。
¶什么是装饰器模式
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
java里面的装饰器模式:
参考这个地址:decorator
🔼上面的地址是github上一个很有名的各种设计模式的java实现。
Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
也就是说:动态的将附加职责添加到对象上。装饰器模式为子类化提供了灵活的代替和扩展的功能。
举个例子:
我们小时候都打过cs,每个警察或者劫匪都可以拿一把武器,或者是AK47,或者是m16,为了更换武器,我们没必要去创造新的角色实例,可以用装饰器动态的用武器装饰他。
// 创建一个角色接口
public interface Person {
void attack();
int getAttackPower();
}
public class Police implements Person {
void attack(){
Systom.out.print("I'm attacking you");
}
int getAttackPower(){
return 5; // 战斗力只有5的渣渣
}
}
public class AkPolice implements Person {
// 提供构造函数来对目标进行包装
public AkPolice(Police decorted) {
this.decorted = decorted;
}
void attack(){
this.decorted.attack()
Systom.out.print("I'm attacking with a Ak!!");//awesome!
}
int getAttackPower(){
return this.decorted.getAttackPower()+100;
}
}
🔼就像上面的简单例子,一个包装类把基本类warped起来,形成了一个新的类,新的类不仅添加了新的动作,还保留了基本类的动作。
优点:
👍 装饰模式与继承关系的目的都是要拓展对象的功能,但是装饰模式可以提供比继承更多的灵活性。装饰模式允许系统动态决定“贴上”一个需要的“装饰”,或者“除掉”一个不需要的“装饰”。继承关系则不同,继承关系是静态的,它在系统运行前就决定了。
👍 通过不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出更多不同行为的组合。
缺点:
👎种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。
装饰器语法最常见的应用就是我们熟悉的java里面的AOP(面向切面)编程,在不影响原有功能的情况下,增加新的处理逻辑,比如添加各种filter,这些filter就像洋葱一样层层包裹,最终执行原有的逻辑,但是在之前和之后,都可以随意添加新的行为,因此,特别适合安全检查,缓存,调试,日志记录等等行为。
¶装饰器语法
第一次看到装饰器语法是在使用python的时候,现在es7也实现了装饰器语法。
首次看到装饰器语法,用过java注解的也许会混到一起,其实这两个东西除了长得像外,原理完全不一样。
Python decorators were inspired in part by Java annotations, and have a similar syntax
--wikipedia
根据wikipedia的说法,装饰器语法的灵感来源于java的注解,所以他们有类似的语法。
注解是利用反射,它本身不改变被注解对象的行为和性质,只有理解这些注解的处理器才会改变行为,在运行的时候起作用。
装饰器实际上是语法糖,利于了python,javascript函数可以赋值,传参的特性,函数是第一公民,函数是对象、是变量,可以作为参数、可以是返回值,对嵌套函数做了简化。
😋引申:如果想了解更多关于javascript函数式特性的知识,可以看下面⬇️
[JS 函数式编程指南中文版 ](https://www.bookstack.cn/read/mostly-adequate-guide-chinese/README.md)
相信看完,你会对javascript有新的认识。
下面重头戏来了,到底在javascript里,怎么实现自己的装饰器呢?
关键的api是Object.defineProperty。
Object.defineProperty(obj, prop, descriptor)
参数:
obj 要在其上定义属性的对象
prop 要定义或修改的属性的名称。
descriptor 将被定义或修改的属性描述符。
装饰器可以用到类,属性和类的方法上,不能用于function❔为什么修饰器不能用于函数?
👍想详细了解装饰器语法,可以去看阮一峰老师的es6教程
下篇博文,我会用实例代码实现不同的装饰器(等我看完上面的教程先😄)。