我正在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)
但是,如果我开始添加更多策略,这似乎会开始变得笨拙/难以维护。还有更好的方法吗?
答案 0 :(得分: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以复杂性为代价实现更大的可扩展性和标准合规性。