我们使用quartz(java API)进行作业调度。这很好用。现在我试图用它来概括一些事情。 quartz api需要一个作业类作为参数来扩展Job接口。这使得通过构造函数传递参数变得不可能。
我们有一组作业都应该做同样的事情,执行检查,如果是,则调用一个动作,例如:
class SimpleJob extends Job {
def execute(context: JobExecutionContext) {
val check = classOf[SimpleCheck].asInstanceOf[Class[Check]].newInstance()
val result = check.execute(context.getJobDetail.getJobDataMap)
if (result.shouldInvokeAction) {
Action(result).execute
}
}
然后通过调用:
实例化石英作业newJob(classOf[SimpleJob]).with...
这很有效。
目标是将此逻辑重用于不同类型的检查 问题:我是否可以使用scala类型系统,我可以使用一个类型的JobClass,可以重复使用它来执行Check的任何子类?
我提出了以下解决方案:
class GenericJobRule[J <: Check](implicit m: Manifest[J]) extends Job {
def execute(context: JobExecutionContext) {
val check = m.erasure.newInstance().asInstanceOf[J]
val result = check.execute(context.getJobDetail.getJobDataMap)
if (result.shouldInvokeAction) {
Action(result).execute
}
}
}
现在可以像这样实例化作业:
newJob(classOf[GenericJobRule[PerformanceCheck]])
这是有效的,但我认为实例化和转换类型绕过了类型检查的整个想法。有没有更好的方法来做到这一点?也许我们应该重新考虑我们的设计......
谢谢,艾伯特
答案 0 :(得分:3)
也许一种可能性是使用类型类。我试图实现它(简化了一些事情),缺点是 特定作业规则始终必须实现doCheck方法(有关类型类的更多信息,请参阅here和here):
[编辑] :用特质替换抽象类。不再需要构造函数参数。
[EDIT2] :忘记类型类(在本例中)。现在变得更简单了。每张支票只是一个特质和一个实施类。你觉得怎么样?
trait GenericJobRule[J <: Check] extends Job {
val genericCheck: J
def execute(context: JobExecutionContext) {
val result = genericCheck.execute(context.getJobDataMap)
if (result.shouldInvokeAction) {
Action(result).execute
}
}
}
class JobRule1 extends GenericJobRule[SimpleCheck] {
override val genericCheck = new SimpleCheck
}
现在可以像这样实例化作业:
newJob(classOf[JobRule1])
[EDIT3] :如果GenericJobRule是一个抽象类,这是另一种可能性:
abstract class GenericJobRule[J <: Check] extends Job {
val genericCheck: J
def execute(context: JobExecutionContext) {
val result = genericCheck.execute(context.getJobDataMap)
if (result.shouldInvokeAction) {
Action(result).execute
}
}
}
然后您可以动态创建特定的作业规则:
val myJobRule = new GenericJobRule[SimpleCheck] { override val genericCheck = new SimpleCheck }