我们的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服务,但是仅此一点就感觉很少。因此:是否有一些现有机制可以赋予我上述工厂功能以动态查找实现?是否要遵循任何模式,示例或最佳做法?
就像注释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);
}
}
现在您可以如下所示创建reporterFactory
和reporterProvider
:
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!!!');
}
}