2012-03-18 69 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

相關問題