TypeScript / JavaScript中的多个Object包装器

时间:2016-10-06 09:55:00

标签: javascript typescript prototypal-inheritance proxy-classes

我有一个接口MyInterface和一个实现接口的具体实现MyImplementation。现在我需要创建多个" Wrappers"这也应该实现MyInterface并将包装原始的MyImplementation对象。从某种意义上说,包装器上的属性和函数方法将作为一种Proxy进行包装 - 即对输入数据执行一些检查并将其传递给MyImplementation的原始实现。我需要将多个包装器堆叠到彼此中,即具有MyValidator1MyValidator2等等,根据用例,可以添加到单个对象中。

一些使事情更清晰的代码:

interface MyInterface {
    method1(arg1, arg2): any;
}

class MyImplementation implements MyInterface {
    method1(arg1, arg2) {
        /* perform checks and or throw */
    }
}

class MyValidator1 implements MyInterface {
    method1(arg1, arg2) {
        /* ... */
    }
}

class MyValidator2 implements MyInterface {
    method1(arg1, arg2) {
        /* ... */
    }
}

let o1 = new MyImplementation();
// only apply validator1
AddValidator1(o1);

let o2 = new MyImplementation();
// only apply validator2
AddValidator2(o2);

let o3 = new MyImplementation();
// apply both validators
AddValidator1(o3);
AddValidator2(o3);

// intended call hierarchicy when calling o3.method1(arg1, arg2)
// MyValidator1.method1(arg1, arg2)
// MyValidator2.method1(arg1, arg2)
// MyImplemenation.method1(arg1, arg2)
// but the order of the validators is not important!

这只是一些代码建议,我正在寻找可能与上述代码不同的各种模式来实现这一目标。

MyInterface实现的所有实例封装起来非常重要 - 它们应该像消费者MyImplemenation一样行事。验证器应该可以添加私有函数或属性。

这是最好的方法吗?也许在运行时改变原型?

2 个答案:

答案 0 :(得分:0)

我不知道TypeScript,但是这里将如何在常规Javascript(ES6语法)中完成:

class MyInterface {
  foo() {
    throw new Error('To be implemented');
  }
}

class MyImplementation extends MyInterface {
  foo() {
    return 42;
  }
}

function wrapWithValidator1(impl) {
  class MyValidator1 extends MyInterface {
    constructor() {
      for (const key of Object.keys(impl)) {
        this[key] = impl[key];
      }
    }

    foo() {
      validateStuff();
      return impl.foo();
    }
  }

  return new MyValidator1();
}

function wrapWithValidator2(impl) {
  class MyValidator2 extends MyInterface {
    constructor() {
      for (const key of Object.keys(impl)) {
        this[key] = impl[key];
      }
    }

    foo() {
      validateOtherStuff();
      return impl.foo();
    }
  }

  return new MyValidator2();
}

您的验证器是实现的包装器,因为它们“扩展”它。它们继承自实现原型(及其所有属性/方法),但它们可以覆盖现有方法以提供其他行为。

覆盖调用父方法的方法时使用super.myMethod()

答案 1 :(得分:0)

如何在MyImplementation班级中列出验证人员?
类似的东西:

abstract class Validator implements MyInterface {
    abstract method1(arg1, arg2): any;
}

class MyValidator1 extends Validator {
    method1(arg1, arg2) {
        /* ... */
    }
}

class MyValidator2 extends Validator {
    method1(arg1, arg2) {
        /* ... */
    }
}

class MyImplementation implements MyInterface {
    private validators: Validator[];

    constructor() {
        this.validators = [];
    }

    addValidator(validator: Validator) {
        this.validators.push(validator);
    }

    method1(arg1, arg2) {
        this.validators.every(validator => { /* do something here */ return false; });
        /* perform checks and or throw */
    }
}

code in playground