代码之家  ›  专栏  ›  技术社区  ›  Artsiom Miksiuk

在不重新定义所有方法的情况下,为长类定义TS中的动态装饰器的方法

  •  0
  • Artsiom Miksiuk  · 技术社区  · 7 年前

    我有一个班,里面有很多方法。让我们不要把重点放在这里,这个类可能被重构并重写为几个类,因为它最终会被重写,但不知道。我想要一个decorator,它只修饰这个类的一个方法。我们可以用几种方法来做到。

    类接口:

    interface IFoo {
        method1 (): number;
        method2 (a: string): number;
        method3 (b: IFoo): number;
        method4 (c: string | (() => string)): number;
        method5 (d: number, e: string): number;
    }
    
    1. 经典的OOP解决方案:定义修饰器,它重新定义特定的方法,并为所有其他方法调用超级实现。像这样。

      class FooDecorator implements IFoo {
          constructor (
              private readonly provider: IFoo
          ) {}
      
          public method1 (): number {
              return this.provider.method1() + 1;
          }
      
          public method2 (a: string): number {
              return this.provider.method2.apply(this.provider, arguments);
          }
      
          public method3 (b: IFoo): number {
              return this.provider.method3.apply(this.provider, arguments);
          }
      
          public method4 (c: string | (() => string)): number {
              return this.provider.method4.apply(this.provider, arguments);
          }
      
          public method5 (d: number, e: string): number {
              return this.provider.method5.apply(this.provider, arguments);
          }
      }
      

      如你所见,写得很长,代码重复。

    2. 尝试使用一些JS功能。

      interface IFooDecorator {
          method1: IFoo["method1"];
      }
      
      class FooDecorator implements IFooDecorator {
          constructor (
              private readonly provider: IFoo
          ) {
              Object.setPrototypeOf(this, provider);
          }
      
          public method1 (): number {
              return this.provider.method1() + 1;
          }
      }
      

      明显的缺点是错误的类型化和setprototypeof的使用

    我也尝试使用代理,但是对于代理的使用也不支持打字。还有其他解决办法吗?第一种方法很好,以防我们可以用 .apply 打电话。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Bergi    7 年前

    将decorator实现为使用 Object.create 而不是 class 语法使您不需要使用 Object.setPrototypeOf :

    function fooDecorator<T>(provider: IFoo): T implements IFoo {
        return Object.create(provider, {
            method1: {
                value(): number {
                    return provider.method1() + 1;
                },
                writable: true,
                configurable: true
            }
        });
    }