2016-09-14 54 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。