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