0

我正在努力为这种“规范化器”类型创建一个父类。我有几个类都共享相同的类结构。我希望有一种方法可以EmailNormalizer在构造函数中包含一些逻辑,并将所有常见功能隐藏在父类中。

我有这个电子邮件规范器类:

export class EmailNormalizer {
  readonly TYPE: string | EmailNormalizer;
  normalized: string;
  constructor(raw: EmailNormalizer['TYPE']) {
    if (!raw) throw new Error('Invalid Email');
    if (raw instanceof EmailNormalizer) {
      this.normalized = raw.normalized;
    } else {
      const results = email.analyze(raw);
      if (results) throw new Error(`Email ${results.error}`);
      this.normalized = _normalizeEmail(raw);
    }
  }
  static normalize(raw: EmailNormalizer['TYPE']) {
    return new EmailNormalizer(raw).normalized;
  }
}

您可以通过两种方式使用它

  • new EmailNormalizer('hello@boom.com').normalize
  • EmailNormalizer.normalize('hello@boom.com')

我正在尝试创建一个共享的“规范器”父类,这样我就不会忘记任何部分。

这是我的第一次尝试。我遇到了静态方法的问题,然后在尝试制作更通用的规范化方法时遇到了问题。

class Normalizer<In = unknown, Out = unknown> {
  readonly TYPE: In;
  normalized: Out;
  normalize: (raw: In) => Out;
  constructor(raw: In) {
    this.normalized = this.normalize(raw);
  }
  static normalize<In, T extends typeof Normalizer>(this: T, raw: In) {
    return new this(raw).normalized;
  }
}

export class EmailNormalizer extends Normalizer<EmailNormalizer | string, string> {
  normalize = (raw: Email['TYPE']) => {
    if (raw instanceof Email) return raw.normalized;
    if (!raw) throw new Error('Invalid Email');
    const results = email.analyze(raw);
    if (results) throw new Error(`Email ${results.error}`);
    return _normalizeEmail(raw);
  };
}

function normalize<I extends any, O extends any, T extends Normalizer<I, O>>(i: T, value) {
  return new i(value).normalized;
}

// ideally
EmailNormalizer.normalize('HELLO@gmail.com');
// or
normalize(EmailNormalizer, 'HELLO@gmail.com')

任何人都可以帮助设计一个规范化的父类吗?

这个父类需要是抽象的吗?

4

1 回答 1

2

我可以建议考虑使用组合而不是继承。例如,一些策略模式在这里会有所帮助:

interface NormalizerStrategy<In, Out> {
  normalize: (raw: In) => Out;
}

class EmailNormalizerStrategy implements NormalizerStrategy<string, string> {
  normalize(raw: string): string {
    // pretend like there is some processing here
    const result = raw;

    return result;
  }
}

class AgeNormalizerStrategy implements NormalizerStrategy<string, number> {
  normalize(raw: string): number {
    // pretend like there is some processing here
    const result = Number(raw);

    return result;
  }
}

class Normalizer<In, Out> {
  constructor(private readonly strategy: NormalizerStrategy<In, Out>) {}

  normalize(input: In): Out {
    this.someProcessingCommonToAllTheStrategies(input);
    
    return this.strategy.normalize(input);
  }

  private someProcessingCommonToAllTheStrategies(data: In): void {
    // pretend like there is some processing here
  }
}

const emailNormalizer = new Normalizer(new EmailNormalizerStrategy);
const normalizedEmail: string = emailNormalizer.normalize('some email');

const ageNormalizer = new Normalizer(new AgeNormalizerStrategy);
const normalizedAge: number = ageNormalizer.normalize('some age');
于 2020-11-24T14:11:34.293 回答