装饰器应用价值

66 阅读7分钟

思维导图

image.png

基本理论

定义

  1. 装饰器就是一个方法或者叫函数,可以写到到类、方法、属性、参数,对象上,基于原有基础上扩展其功能。

为什么要用

  1. 从规范来讲,尽量少用继承,优先用对象进行扩充。

  2. 关键点在于切面:其由切点和增强点组成:类比于 before after.

  3. 为前端补充了 AOP 面向切面编程思想:

    1. AOP
    2. 目的将业务功能和基础架构功能相分离:Log 日志举例子:
    3. //不直接写log是因为不想将基础架构功能嵌入到业务代码里造成耦合。
      function log(target: any, key: string, descriptor: PropertyDescriptor) {
        const oldValue = descriptor.value // fn1 函数 // 重新定义 fn1 函数 
        descriptor.value = function () {
          console.log(`记录日志...`)
          return oldValue.apply(this, arguments)
        }
      }
      
      class Foo {
        @log
        fn1() { console.log('业务功能1') }
      
      }
      const f = new Foo()
      f.fn1()
      
  4. 监控系统(性能,错误,行为分析)。

  5. 前置拦截以及后置拦截:执行原有函数前,做一些事情,执行原有函数后,还需要做一些事情

执行时机

  1. 编译阶段就执行了。所以说装饰器函数真正能触及到的,就只有类这个层面上的对象(类的原型对象):
  2. // 不带参数的装饰器
    function FirstClassDecorator1(targetClass:any ) {
      let targetClassObj = new targetClass();
      targetClassObj.buy();
      console.log("targetClass.name:", targetClass.name);
    }
    function SecondClassDecorator(targetClass: any) {
      let targetClassObj = new targetClass();
      targetClassObj.buy();
      console.log("targetClass.name:", targetClass.name);
    }
    
    @FirstClassDecorator1
    class CustomerService {
      name: string = "下单"
      constructor() {
      }
      buy() {
        console.log(this.name + "购买");
      }
      placeOrder() {//下单
        console.log(this.name + "下单购买");
      }
    }
    

弊端

  1. 函数式组件会出现函数提升的问题:高阶组件解决;
  2. function doSomething(name) {
      console.log('Hello, ' + name);
    }
    
    function loggingDecorator(wrapped) {
      return function() {
        console.log('Starting');
        const result = wrapped.apply(this, arguments);
        console.log('Finished');
        return result;
      }
    }
    
    const wrapped = loggingDecorator(doSomething);
    
  3. 多层装饰器会加大项目复杂度

设计原则

  1. 单一指责:每个装饰器只扩展一个功能。
  2. 以及开放封闭原则:仅仅对现有功能进行扩展,新旧逻辑解耦。

本质

  1. 就是函数,也是 @ 符的语法糖。

分类

  1. 类装饰器、属性装饰器、方法装饰器、参数装饰器,元数据装饰器

前端应用

react-redux

AOP

  1. 优势:非侵入式。

Angular

  1. import { Component, OnInit } from '@angular/core';
    
    @Component({
      selector: 'app-product-alerts',//选择器
      templateUrl: './product-alerts.component.html',//模板template
      styleUrls: ['./product-alerts.component.css']//样式表链接
    })
    export class ProductAlertsComponent implements OnInit {
    
      constructor() { }
    
      ngOnInit() {
      }
    
    }
    

项目如何落地

  1. 为什么要用:旧有添加逻辑自定义属性 id,针对特定的组件需要改动源代码,同时对于纯自定也业务组件,难以支持打标签。
  2. 能够解决什么问题:首先符合开放封闭原则,形成通用解决方案,避免特定组件,差异处理。
  3. 初版方案:装饰器指责:能够精准在目标标签上打上 id,监控 sdk 负责埋点,上报用户信息,不再让装饰器承担过多的职责。

基本理论

定义

  1. 装饰器就是一个方法或者叫函数,可以写到到类、方法、属性、参数,对象上,基于原有基础上扩展其功能。

为什么要用

  1. 从规范来讲,尽量少用继承,优先用对象进行扩充。

  2. 关键点在于切面:其由切点和增强点组成:类比于 before after.

  3. 为前端补充了 AOP 面向切面编程思想:

    1. AOP
    2. 目的将业务功能和基础架构功能相分离:Log 日志举例子:
    3. //不直接写log是因为不想将基础架构功能嵌入到业务代码里造成耦合。
      function log(target: any, key: string, descriptor: PropertyDescriptor) {
        const oldValue = descriptor.value // fn1 函数 // 重新定义 fn1 函数 
        descriptor.value = function () {
          console.log(`记录日志...`)
          return oldValue.apply(this, arguments)
        }
      }
      
      class Foo {
        @log
        fn1() { console.log('业务功能1') }
      
      }
      const f = new Foo()
      f.fn1()
      
  4. 监控系统(性能,错误,行为分析)。

  5. 前置拦截以及后置拦截:执行原有函数前,做一些事情,执行原有函数后,还需要做一些事情

执行时机

  1. 编译阶段就执行了。所以说装饰器函数真正能触及到的,就只有类这个层面上的对象(类的原型对象):
  2. // 不带参数的装饰器
    function FirstClassDecorator1(targetClass:any ) {
      let targetClassObj = new targetClass();
      targetClassObj.buy();
      console.log("targetClass.name:", targetClass.name);
    }
    function SecondClassDecorator(targetClass: any) {
      let targetClassObj = new targetClass();
      targetClassObj.buy();
      console.log("targetClass.name:", targetClass.name);
    }
    
    @FirstClassDecorator1
    class CustomerService {
      name: string = "下单"
      constructor() {
      }
      buy() {
        console.log(this.name + "购买");
      }
      placeOrder() {//下单
        console.log(this.name + "下单购买");
      }
    }
    

弊端

  1. 函数式组件会出现函数提升的问题:高阶组件解决;
  2. function doSomething(name) {
      console.log('Hello, ' + name);
    }
    
    function loggingDecorator(wrapped) {
      return function() {
        console.log('Starting');
        const result = wrapped.apply(this, arguments);
        console.log('Finished');
        return result;
      }
    }
    
    const wrapped = loggingDecorator(doSomething);
    
  3. 多层装饰器会加大项目复杂度

设计原则

  1. 单一指责:每个装饰器只扩展一个功能。
  2. 以及开放封闭原则:仅仅对现有功能进行扩展,新旧逻辑解耦。

本质

  1. 就是函数,也是 @ 符的语法糖。

分类

  1. 类装饰器、属性装饰器、方法装饰器、参数装饰器,元数据装饰器

前端应用

react-redux

AOP

  1. 优势:非侵入式。

Angular

  1. import { Component, OnInit } from '@angular/core';
    
    @Component({
      selector: 'app-product-alerts',//选择器
      templateUrl: './product-alerts.component.html',//模板template
      styleUrls: ['./product-alerts.component.css']//样式表链接
    })
    export class ProductAlertsComponent implements OnInit {
    
      constructor() { }
    
      ngOnInit() {
      }
    
    }
    

项目如何落地

  1. 为什么要用:旧有添加逻辑自定义属性 id,针对特定的组件需要改动源代码,同时对于纯自定也业务组件,难以支持打标签。
  2. 能够解决什么问题:首先符合开放封闭原则,形成通用解决方案,避免特定组件,差异处理。
  3. 初版方案:装饰器指责:能够精准在目标标签上打上 id,监控 sdk 负责埋点,上报用户信息,不再让装饰器承担过多的职责。

基本理论

定义

  1. 装饰器就是一个方法或者叫函数,可以写到到类、方法、属性、参数,对象上,基于原有基础上扩展其功能。

为什么要用

  1. 从规范来讲,尽量少用继承,优先用对象进行扩充。

  2. 关键点在于切面:其由切点和增强点组成:类比于 before after.

  3. 为前端补充了 AOP 面向切面编程思想:

    1. AOP
    2. 目的将业务功能和基础架构功能相分离:Log 日志举例子:
    3. //不直接写log是因为不想将基础架构功能嵌入到业务代码里造成耦合。
      function log(target: any, key: string, descriptor: PropertyDescriptor) {
        const oldValue = descriptor.value // fn1 函数 // 重新定义 fn1 函数 
        descriptor.value = function () {
          console.log(`记录日志...`)
          return oldValue.apply(this, arguments)
        }
      }
      
      class Foo {
        @log
        fn1() { console.log('业务功能1') }
      
      }
      const f = new Foo()
      f.fn1()
      
  4. 监控系统(性能,错误,行为分析)。

  5. 前置拦截以及后置拦截:执行原有函数前,做一些事情,执行原有函数后,还需要做一些事情

执行时机

  1. 编译阶段就执行了。所以说装饰器函数真正能触及到的,就只有类这个层面上的对象(类的原型对象):
  2. // 不带参数的装饰器
    function FirstClassDecorator1(targetClass:any ) {
      let targetClassObj = new targetClass();
      targetClassObj.buy();
      console.log("targetClass.name:", targetClass.name);
    }
    function SecondClassDecorator(targetClass: any) {
      let targetClassObj = new targetClass();
      targetClassObj.buy();
      console.log("targetClass.name:", targetClass.name);
    }
    
    @FirstClassDecorator1
    class CustomerService {
      name: string = "下单"
      constructor() {
      }
      buy() {
        console.log(this.name + "购买");
      }
      placeOrder() {//下单
        console.log(this.name + "下单购买");
      }
    }
    

弊端

  1. 函数式组件会出现函数提升的问题:高阶组件解决;
  2. function doSomething(name) {
      console.log('Hello, ' + name);
    }
    
    function loggingDecorator(wrapped) {
      return function() {
        console.log('Starting');
        const result = wrapped.apply(this, arguments);
        console.log('Finished');
        return result;
      }
    }
    
    const wrapped = loggingDecorator(doSomething);
    
  3. 多层装饰器会加大项目复杂度

设计原则

  1. 单一指责:每个装饰器只扩展一个功能。
  2. 以及开放封闭原则:仅仅对现有功能进行扩展,新旧逻辑解耦。

本质

  1. 就是函数,也是 @ 符的语法糖。

分类

  1. 类装饰器、属性装饰器、方法装饰器、参数装饰器,元数据装饰器

前端应用

react-redux

AOP

  1. 优势:非侵入式。

Angular

  1. import { Component, OnInit } from '@angular/core';
    
    @Component({
      selector: 'app-product-alerts',//选择器
      templateUrl: './product-alerts.component.html',//模板template
      styleUrls: ['./product-alerts.component.css']//样式表链接
    })
    export class ProductAlertsComponent implements OnInit {
    
      constructor() { }
    
      ngOnInit() {
      }
    
    }
    

项目如何落地

  1. 为什么要用:旧有添加逻辑自定义属性 id,针对特定的组件需要改动源代码,同时对于纯自定也业务组件,难以支持打标签。
  2. 能够解决什么问题:首先符合开放封闭原则,形成通用解决方案,避免特定组件,差异处理。
  3. 初版方案:装饰器指责:能够精准在目标标签上打上 id,监控 sdk 负责埋点,上报用户信息,不再让装饰器承担过多的职责。