2017-04-14 1 views
1

Ich versuche, ein Jobausführungsmodul zu schreiben, das eine Factory verwendet, um je nach Art des Jobs Logik zum Ausführen eines Jobs bereitzustellen.Scala - Liefern verschiedener Abhängigkeiten zu untergeordneten Klassen Instanziiert von Factory

Die Quandry, die ich habe, ist, wie verschiedene Abhängigkeiten zu den spezifischen Implementierungen zu liefern, während eine generische Signatur für Instanziierung.

Der gekürzte Code folgt.

Basisklasse mit Hersteller:

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) 
} 

Ein eingehender Auftrag thusly ausgeführt wird:

// Note that here I have the services in scope that I would like to supply to the job execution implementation. 

JobExecution(someJob, jobService).execute 

Ich brauche eine Implementierung, so etwas haben:

class SomeJobExecImpl(job: Job, jobService: JobService, otherService: OtherService) 
    extends JobExecution(job, jobService) { 
    def execute: Unit = ??? 
} 

Oder vielleicht:

class SomeJobExecImpl(job: Job, jobService: JobService) 
        (implicit otherService: OtherService) 
    extends JobExecution(job, jobService) { 
    def execute: Unit = ??? 
} 

Ich war nicht in der Lage, eine Lösung jenseits einiger stinkender Workarounds zu finden.

Gibt es einen schlüssigen Weg, wie ich dies unter Beibehaltung des Grundmusters tun kann, oder erfordert es eine Großhandelsänderung?

Beachten Sie, dass ich keine DI-Bibliothek verwende.

Antwort

2

Mit minimaler Änderung Ihrer bestehenden Struktur, eine Option ist, alle Ihre Dienste zur Liste heraus in einem ServiceRegistry wie:

trait ServiceRegistry { 
    implicit val jobService: JobService 
    implicit val otherService: OtherService 
    ... 
} 

dann Ihre JobExecution Registrierung ändern:

... 
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) 
} 

Und wenn ein JobExecution Implementierung erfordert zusätzliche Dienste:

class SomeJobExecImpl(job: Job, jobService: JobService) 
        (implicit otherService: OtherService) 
    extends JobExecution(job, jobService) { 
    def execute: Unit = ??? 
} 
+0

Dies Ähnelt einer der Optionen, die ich bereits erfunden habe - mit einem einzigen Container für die Dienstabhängigkeiten. Ich werde sehen, ob ich damit arbeiten kann. Danke für den Vorschlag. – manadart

+0

Dies funktioniert gut. Der Aufrufer der Jobausführung implementiert das Merkmal ohne Codeänderungen, so dass es einfach ist, "this" an die Factory-Methode zu übergeben. – manadart

Verwandte Themen