2012-03-18 70 views
1

我有一个应该生产汽车并与他们一起操作的应用程序。汽车对象的创建是一个复杂的过程,所以我需要为每种类型的汽车提供一个工厂。另外我希望用户能够提供他们自己的汽车和生产它们的工厂。这些汽车类型和工厂应该插入我的应用程序作为罐子(可能有更好的方式比罐子,但我没有看到它)。应用程序启动时动态触发对象方法

我已经想出了一个制作一个接受汽车名称(“mercedes”,“bmw”,“nissan”等)作为参数的通用CarFactory的概念。 CarFactory有一个映射,其中每个名称映射到它自己的工厂类。该代码看起来是这样的(抱歉,我不能提供一个工作拷贝,因为我仍在评估,并没有哪个编译没有错误的版本)

import scala.collection.mutable.Map 

class CarFactory { 
    var knownCarTypes = Map[String, Class[Factory]]() 

    def create(carType: String) = knownCarTypes.get(carType) match { 
     case Some(factoryClass) => Some(factoryClass.getMethod("create").invoke(null).asInstanceOf[Car]) 
     case None => None 
    } 
    } 
} 

的knownCarTypes是可变的,因为我想用户工厂在该地图上注册,提供他们负责的汽车类型以及工厂类别的名称。因此,从用户类看起来像这样

class Mercedes extends Car 

object MercedesFactory extends Factory { 
    def register() { 
    CarFactory.knownCarTypes("mercedes") = getClass 
    } 

    def create() = new Mercedes() 
} 

这是我的问题。我不知道如何触发用户工厂的注册()方法。可能吗?有没有比我的方法更好的解决方案?

我想过为工厂制定共同的特质,找到所有通过反射实现特质和触发方法的加载类。但看起来相当复杂。我希望可以在这里使用一些设计模式或OOP技巧。你怎么看?

谢谢!

+1

作为提示,如果您使用可变映射,则不需要将其声明为var。 '+ ='会在原地进行修改。 – 2012-03-18 14:44:15

+0

哦..你说得对。谢谢:) – Soteric 2012-03-18 14:56:16

回答

1

最后我得到了它通过反射工作。我遍历指定路径上的所有jar,发现所有类实现我的com.example.Factory特征并触发它们的寄存器()方法。对于罐子检查我用Clapper ClassFinder和调用对象的方法,我也跟着Thomas Jung advice.下面是最终代码

import org.apache.commons.io.FileUtils 
import org.clapper.classutil.{ClassFinder, ClassInfo} 
import scala.collection.JavaConverters._ 

def triggerFactories() { 
    val jars = FileUtils.iterateFiles(new File("lib"), Array[String]("jar"), true).asScala.toList 
    val classes = ClassFinder(jars).getClasses 
    val factories = ClassFinder.concreteSubclasses("com.example.Factory", classes) 

    factories.foreach { (factory: ClassInfo) => 
    companion[Factory](factory.name).register() 
    } 
} 

def companion[T](name: String)(implicit man: Manifest[T]): T = 
    Class.forName(name).getField("MODULE$").get(man.erasure).asInstanceOf[T] 

它为我工作。它看起来很棘手,但我希望它在将来不会破坏我的应用程序中的任何内容。如果有更好的方法,请发帖,我会接受答案。

1

如果我正确理解你的问题,你所要做的就是从对象的“身体”通话记录:

object MercedesFactory extends Factory { 
    def register() { 
    CarFactory.knownCarTypes("mercedes") = getClass 
    } 
    register 

    def create() = new Mercedes() 
} 
+0

不幸的是,直到我触摸MercedesFactory对象(以任何方式,通过调用它的任何方法)它不会调用对象体:( – Soteric 2012-03-18 16:33:47

相关问题