在Nestjs中,我有一个模块,它使用useFactory动态创建基于configValue的类
该模块中没有专门的服务,而是返回一个依赖于配置的服务,因此DriverService1和DriverService2将一起构建
export const createFactory = (config: IConfig):Provider<IService> => {
return {
provide: 'FACTORY',
useFactory: (service1: DriverService1, service2: DriverService2): IService => {
if (config.driver == 'DriverService1')
{
return service1;
}
else if (config.driver == 'DriverService2')
{
return service2;
}
throw new Error('not implemented')
},
inject: [ DriverService1, DriverService2 ],
}
};
@Module({})
export class MyModule {
static register(config?: IConfig): DynamicModule {
const factory = createFactory(config)
return {
module: MyModule,
providers: [
{
provide: 'CONFIG',
useValue: config,
},
DriverService1,
DriverService2,
factory
],
exports: [factory],
};
}
}
但我不确定这是正确的方法
或者我应该在这个模块中创建一个专用服务,例如“MyModuleService”,然后在服务中执行工厂模式?驱动程序仅在使用时才会构造
interface IDriver {
action1():void
action2():void
action3():void
}
class Driver1 implements IDriver{
public action1():void {
console.log("DriverService1 action1")
}
public action2():void {
console.log("DriverService1 action2")
}
public action3():void {
console.log("DriverService1 action3")
}
}
class Driver2 implements IDriver{
public action1():void {
console.log("DriverService2 action1")
}
public action2():void {
console.log("DriverService2 action2")
}
public action3():void {
console.log("DriverService2 action3")
}
}
export const createFactory = (config: IConfig):Provider<MyModuleSerice> => {
return {
provide: 'BROKER_FACTORY',
useFactory: (service:MyModuleSerice): MyModuleSerice => {
if (config.driver == 'Driver1')
{
service.setDriver(new Driver1());
}
else if (config.driver == 'Driver2')
{
service.setDriver(new Driver2());
}
else{
throw new Error('not implemented')
}
return service
},
inject: [ MyModuleSerice ],
}
};
@Module({})
export class MyModule {
static register(config?: IConfig): DynamicModule {
const facotry = createFactory(config)
return {
module: MyModule,
providers: [
{
provide: 'CONFIG',
useValue: config,
},
facotry
],
exports: [facotry],
};
}
}
@Injectable()
class MyModuleSerice {
protected driver:IDriver
constructor() {
}
public setDriver(driver:IDriver) {
this.driver = driver
}
public doSomething():void {
this.driver.action1()
this.driver.action2()
}
public doSomething2():void {
this.driver.action1()
this.driver.action3()
}
}
这就是提供商发挥作用的地方。您可以创建一个可以为您处理此逻辑的自定义提供程序。见下文。
https://docs.nestjs.com/fundamentals/custom-providers
这是 NestJS 提供的示例,它利用配置文件来创建服务实例。
const configServiceProvider = {
provide: ConfigService,
useClass:
process.env.NODE_ENV === 'development'
? DevelopmentConfigService
: ProductionConfigService,
};
@Module({
providers: [configServiceProvider],
})
export class AppModule {}
让我们首先了解两种方法之间的区别,然后再确定哪种方法更好。
方法 1:您已经创建了一个模块,它将根据提供的配置提供驱动程序实例。这可以被认为是一个 DriverFactoryModule。
方法 2:您创建了一个模块,该模块返回一个封装驱动程序实例的服务(基于提供的配置),主要目的是提供执行可以使用驱动程序实例执行的操作的功能。这种方法不会公开驱动程序实例本身。
在这两种方法中,您打算使用工厂模式根据用户的需求创建驱动程序实例。然而,工厂模式的实现依赖于抽象,即工厂类依赖于接口或抽象,并根据用户的请求创建具体的实例。在实现方面,工厂模式实现在第二种方法中遵循了这一原则。您可以通过更改命名约定来进行另一项改进(例如,DriverFactory 服务(模块内部)使用方法“getDriverInstance”,该方法扮演工厂的角色并在提供程序内部使用它:(userFactory))。
那么,现在让我们来讨论主要问题 - 哪种方法更好?这完全取决于模块的预期。模块应该只返回驱动程序实例还是应该返回封装驱动程序实例的 DriverService