2016-09-14 55 views
4

我正在Java/Kotlin中實施學習代理。該代理的部分功能涉及通過大量可能的選項進行搜索。搜索可能性空間有很多好方法,我經常改變我的想法,哪一個最好。因此,我決定把它作爲一種戰略模式來實施。通過JSON配置選擇策略配置

class Agent(val searchStrategy : SearchStrategy){ 
    fun search(input : InputGraph) : Result{ 
     return searchStrategy.search() 
    } 
} 

interface SearchStrategy{ 
    fun search(input : InputGraph) : Result 
} 

class FastSearch : SearchStrategy{ 
    //implementation here 
} 

class AccurateSearch : SearchStrategy{ 
    // implementation here 
} 

class ExperimentalSerach : SearchStrategy{ 
    // implentation here 
} 

最近,我決定運行一大組實驗來測試各種系統參數的有效性。這是通過一個python腳本完成的,該腳本通過運行帶有不同config.json文件的編譯jar作爲參數來踢每個實驗。例如:

{ 
    "numSamples" : 5000, 
    "environmentDifficulty" : 3, 
    "hazardProbability" : 0.4, 
    //etc.. 
} 

我現在想給實驗者配置代理使用的策略的能力。做這個的最好方式是什麼?我立即想到的是,我只需要添加一個額外的字符串字段到config.json:

{ 
    "numSamples" : 5000, 
    "environmentDifficulty" : 3, 
    "hazardProbability" : 0.4, 
    "agentStrategy": "FastSearch" 
} 

然後用它構建在主系統何時或是否分支:

val searchStrategy = when(config.agentStrategy){ 
    "FastSearch" -> FastSearch() 
    "AccurateSearch" -> AccurateSearch() 
    "ExperimentalSearch" -> ExperimentalSearch() 
val agent = agent(searchStrategy) 

但這似乎如果我開始添加更多策略,它將開始變得難以維護/難以維護。有沒有更好的辦法?

回答

5

一個解決這個問題的方法是使用類名像這樣加載和創建戰略的一個實例:

val agentClass = classLoader.loadClass(config.agentStrategy)!! 
val agent = agentClass.newInstance() as SearchStrategy 

另一種方式是註冊所有的搜索策略,然後匹配一個使用給定config像所以:

class SearchStrategies(val strategies: List<SearchStrategy>){ 
    fun findForConfig(config:Config) = strategies.find { it.javaClass.name.contains(config.agentStrategy) } 
} 


//somewhere at boot time 
val searchStrategies = SearchStrategies(listOf(FastSearch(), AccurateSearch())) 


//when needed 
val config = ... 
val agent = searchStrategies.findForConfig(config) 

最後它也可以利用SPI在複雜的成本實現更高的可擴展性和標準complianace。