zoukankan      html  css  js  c++  java
  • 设计模式:装饰器

    概念:装饰器作用是在在不会影响原有方法或类的功能的前提下,对它们进行增强。 属于AOP面向切面编程下的一种设计方案,更“优雅”地把“辅助功能逻辑”从“业务逻辑”中分离。( 比如将日志记录,性能统计,安全控制,异常处理等代码从业务逻辑代码中解耦出来出来)

    本质:装饰器语法本质是  Object.defineProperty,装饰器是基于Object.definePropert的语法糖。

    Object.defineProperty(obj, prop, descriptor)
    
    • 第一个参数是要装饰的对象target
    • 第二个参数是对象的属性名key
    • 第三个参数是该属性的描述对象descriptor
    /**
     * {
     *   configurable: true,  // 可配置的
     *   enumerable: true,    // 可枚举的
     *   value: () => {},     // 该属性对应的值(数值,对象,函数,正则,日期等)
     *   writable: true,      // 可写入的
     * }
     */
    
    
    var a = { b: () => {} }
    var descriptor = Object.getOwnPropertyDescriptor(a, 'b')
    console.log(descriptor)
    

     

    五种装饰器

    属性装饰器

    type PropertyDecorator = (target: Object, propertyKey: string | symbol) => any;
    
    let nameDecorator: PropertyDecorator = (target, propertyKey) => {
    
      const descriptor: PropertyDescriptor = {
        writable: true,
      };
    
      return descriptor
    }
    

      

    方法装饰器:(作用在类的方法上)

    接受  target,name,descriptor 三个参数

    interface PropertyDescriptor {
      configurable?: boolean;
      enumerable?: boolean;
      value?: any;
      writable?: boolean;
      get?(): any;
      set?(v: any): void;
    }
    
    
    // tyoe 实现
    type MethodDecorator = (target: Object,name: PropertyKey,descriptor: PropertyDescriptor) =>PropertyDescriptor;
    
    
    //interface 实现
    
    interface  MethodDecorator2{
      (target: Object,name: string|symbol,descriptor: PropertyDescriptor):PropertyDescriptor
    }
    

     实现日志模块 

    let log = (type:string):MethodDecorator2 => {
    
      return (target, name, descriptor)  => {
        const method = descriptor.value;
        descriptor.value =  (...args) => {
          console.info(`(${type}) 正在执行: ${name}(${args}) = ?`);
          let ret;
          try {
            ret = method.apply(target, args);
            console.info(`(${type}) 成功 : ${name}(${args}) => ${ret}`);
          } catch (error) {
            console.info(`(${type}) 失败: ${name}(${args}) => ${error}`);
          }
          return ret;
        }
        return descriptor
      }
    }
    
    
    
    class IronMan {
      @log('IronMan 自检阶段')
      check(){
        return '检查完毕';
      }
      @log('IronMan 攻击阶段')
      attack(){
        return '击倒敌人';
      }
      @log('IronMan 机体报错')
      error(){
        throw 'Something is wrong!';
      }
    }
    
    var tony = new IronMan();
    tony.check();
    tony.attack();
    

      

     类装饰器:(作用在类上 decorator)

    hoc

    function hocComponent(namespace) {
      return WrappedComponent => {
        return class extends React.Component {
          constructor(props) {
            super(props);
         
          }
    
          render() {
            const pp= Object.assign({}, this.props, {
              name: namespace
            });
    
            
            return <div>
              <WrappedComponent {...pp} />
              <div>{namespace}</div>
            </div>;
          }
    
          componentWillUnmount() {
           
          }
        };
      };
    }
    
    // 装饰组件
    @hocComponent('eventSpace')
    class Dashboard  extends React.Component {
      constructor(props) {
        super(props);
     
      }
      render() {
     
        return <div>222{this.props.name}3</div>;
      }
    }
    export default Dashboard;
    

      

      

    作用在类上的 decorator, 接受一个target 参数是类本身,从而对类添加静态属性

    // 这里的 `target` 是类本身
    function doge (target) {
      target.isDoge = true
    }
    
    @doge
    class Dog {}
    
    console.log(Dog.isDoge)
    // true
    

      

     

      

     

  • 相关阅读:
    WinRAR v5.90中文正式32&64位整合安装版
    WIN10永久激活工具 HWIDGEN
    Adobe2020套装激活工具
    keka 1.1.26-压缩工具
    python文件和目录操作方法大全(含实例)
    如何使公网能够访问本地web服务器?
    网线那根正极那根负极
    HPUX 大文件系统扩容
    LESS详解之函数(四)
    Win7 安装Apache 2.2.4报错:<OS 5>拒绝访问. :Failed to open the WinNT service manager
  • 原文地址:https://www.cnblogs.com/breakdown/p/15209466.html
Copyright © 2011-2022 走看看