装饰器的简单实现(上)

Author Avatar
zzz1220 7月 01, 2019
  • 在其它设备中阅读本文章
👉👉本文共1.3k字📘 读完共需4分钟⌚

es7javascript添加了激动人心的新特性----装饰器,不过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里,怎么实现自己的装饰器呢?

关键的apiObject.defineProperty

Object.defineProperty(obj, prop, descriptor)

参数:

obj 要在其上定义属性的对象

prop 要定义或修改的属性的名称。

descriptor 将被定义或修改的属性描述符。

装饰器可以用到,属性和类的方法上,不能用于function为什么修饰器不能用于函数?

👍想详细了解装饰器语法,可以去看阮一峰老师的es6教程

修饰器

下篇博文,我会用实例代码实现不同的装饰器(等我看完上面的教程先😄)。