动态查找服务实现

问题描述 投票:0回答:1

我们的Angular应用程序提供的服务也可以具有不同的实现。 “策略”。为简单起见,我们假设它是一项“事件报告”服务。事件报告服务具有报告信息的功能。根据运行时的偏好,报告可以关闭,转到console或发送到REST API或其他地方。

使用纯TS,这看起来像:

interface IReporter {
  report (message: string): void;
}

class NoReporter implements IReporter {
  report (message: string): void {
    // no op.
  }
}

class ConsoleReporter implements IReporter {
  report (message: string): void {
    console.log(message);
  }
}

// etc.

[在消费者中,我建了一家工厂,可以提供所需的记者,例如基于用户偏好设置:

getReporter (key: string): IReporter {
  switch (key) {
    // … tedious cases, which need to be mainted. Yikes!
  }
}

但是,这感觉不太像“角度”。第一步可能是为单个记者提供适当的Angular服务,但是仅此一点就感觉很少。因此:是否有一些现有机制可以赋予我上述工厂功能以动态查找实现?是否要遵循任何模式,示例或最佳做法?

angular factory strategy-pattern
1个回答
0
投票

就像注释FactoryProviders中提到的那样,可以完美解决此问题。

您必须将您的IReporter接口定义为class interface,因为接口在运行时不存在,因此它们不是有效的DI令牌:

export abstract class IReporter {
  report: (message: string) => void;
}

@Injectable()
export class NoReporter implements IReporter{
  report(message:string):void{

  }
}

@Injectable()
export class ConsoleReporter implements IReporter {
  report(message: string): void {
    console.log(message);
  }
}

现在您可以如下所示创建reporterFactoryreporterProvider

const reporterFactory = (key: string) => {
  switch (key) {
    case 'no-report':
      return () => new NoReporter();
    case 'console-report':
      return () => new ConsoleReporter();
    default:
      return () => new ConsoleReporter();
  }
};

export const reporterProvider = (key: string) => {
  return {
    provide: IReporter,
    useFactory: reporterFactory(key)
  }
};

并在您的组件中插入一个记者:

@Component({
  selector: 'test',
  template: `TESTCOMPONENT`,
  providers: [
    reporterProvider('console-report')
  ]
})
export class TestComponent {
  constructor(private reporter: IReporter) {
    reporter.report('it works!!!');
  }

}
© www.soinside.com 2019 - 2024. All rights reserved.