通过JSON配置选择策略

我正在Java / Kotlin中实施一个学习代理。 该代理功能的一部分涉及通过大量可能的选项进行搜索。 搜索可能性空间有很多好方法,我经常改变我的想法,哪一个是最好的。 所以我决定把它作为一个战略模式来实施。

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" } 

然后用一个when或if分支在主系统中构造它:

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

但是,如果我开始增加更多的策略,似乎会开始变得难以维系。 有没有更好的办法?

    解决这个问题的一个方法是使用类名来加载和创建策略的一个实例,如下所示:

     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来实现更高的可扩展性和标准兼容性,但这是以复杂性为代价的。