我正在尝试编写一个作业执行模块,该模块使用工厂来提供执行作业的逻辑,具体取决于作业的类型。
我遇到的困境是如何为特定实现提供不同的依赖项,同时保留通用签名以进行实例化。
删节代码如下。
带工厂的基类:
abstract class JobExecution(job: Job, jobService: JobService) {
def execute: Unit
}
object JobExecution {
val registry: Map[Long, (Job, JobService) => JobExecution] = Map(
1L -> ((j: Job, s: JobService) =>
new SomeJobExecImpl(j, s).asInstanceOf[JobExecution])
)
def apply(job: Job, service: JobService): JobExecution = registry(job.jobTypeId)(job, service)
}
传入作业以这种方式执行:
// Note that here I have the services in scope that I would like to supply to the job execution implementation.
JobExecution(someJob, jobService).execute
我需要像这样实现:
class SomeJobExecImpl(job: Job, jobService: JobService, otherService: OtherService)
extends JobExecution(job, jobService) {
def execute: Unit = ???
}
或者也许:
class SomeJobExecImpl(job: Job, jobService: JobService)
(implicit otherService: OtherService)
extends JobExecution(job, jobService) {
def execute: Unit = ???
}
除了一些臭味的解决方法之外,我无法设计出解决方案。
是否有令人信服的方法可以在保留基本模式的同时做到这一点,还是需要大规模更改?
请注意,我没有使用 DI 库。
只需对现有结构进行最少的更改,一种选择是在ServiceRegistry
中列出所有服务,如下所示:
trait ServiceRegistry {
implicit val jobService: JobService
implicit val otherService: OtherService
...
}
然后更改JobExecution
注册表:
...
object JobExecution {
val registry: Map[Long, (Job, ServiceRegistry) => JobExecution] = Map(
1L -> ((j: Job, r: ServiceRegistry) =>
import r._
new SomeJobExecImpl(j, r.jobService).asInstanceOf[JobExecution])
)
def apply(job: Job, serviceReg: ServiceRegistry): JobExecution =
registry(job.jobTypeId)(job, serviceReg)
}
当JobExecution
实施需要其他服务时:
class SomeJobExecImpl(job: Job, jobService: JobService)
(implicit otherService: OtherService)
extends JobExecution(job, jobService) {
def execute: Unit = ???
}