通过JSON配置选择策略

Cra*_*nes 4 java configuration json design-patterns kotlin

我正在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
}
Run Code Online (Sandbox Code Playgroud)

最近,我决定运行一系列实验来测试各种系统参数的有效性.这是通过python脚本完成的,它通过运行带有不同config.json文件的编译jar作为参数来完成每个实验.就像是:

{
    "numSamples" : 5000,
    "environmentDifficulty" : 3,
    "hazardProbability" : 0.4,
    //etc..
}
Run Code Online (Sandbox Code Playgroud)

我现在想让实验者能够配置代理使用的策略.做这个的最好方式是什么?我的直接想法是我可以在config.json中添加一个额外的字符串字段:

{
    "numSamples" : 5000,
    "environmentDifficulty" : 3,
    "hazardProbability" : 0.4,
    "agentStrategy": "FastSearch"
}
Run Code Online (Sandbox Code Playgroud)

然后使用when或if分支在主系统中构建它:

val searchStrategy = when(config.agentStrategy){
    "FastSearch" -> FastSearch()
    "AccurateSearch" -> AccurateSearch()
    "ExperimentalSearch" -> ExperimentalSearch()
val agent = agent(searchStrategy)
Run Code Online (Sandbox Code Playgroud)

但是,如果我开始添加更多策略,这似乎会开始变得笨拙/难以维护.有没有更好的办法?

mie*_*sol 5

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

val agentClass = classLoader.loadClass(config.agentStrategy)!!
val agent = agentClass.newInstance() as SearchStrategy
Run Code Online (Sandbox Code Playgroud)

另一种方法是注册所有搜索策略,然后使用给定的匹配方式匹配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)
Run Code Online (Sandbox Code Playgroud)

最后,还可以利用SPI以复杂性为代价实现更大的可扩展性和标准合规性.