2017-04-14 50 views
1

我试图编写一个工作执行模块,它使用工厂来提供执行作业的逻辑,具体取决于作业的类型。Scala - 向工厂实例化的子类提供不同的依赖关系

我有的困惑是如何提供不同依赖关系的具体实现,同时保留实例化的通用签名。

接下来的代码如下。

基类工厂:

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库。

回答

2

用最少的改变现有的结构,一种选择是,列出你所有的服务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 = ??? 
} 
+0

This与我已经设计的选项之一有一些相似之处 - 具有用于服务依赖关系的单个容器。我会看看我是否可以使用它。感谢您的建议。 – manadart

+0

事实证明,这很好。作业执行调用程序在没有任何代码更改的情况下实现特征,因此只需将“this”传递给工厂方法即可。 – manadart