Elegir una estrategia a través de la configuration JSON

Estoy implementando un agente de aprendizaje en Java / Kotlin. Parte de la funcionalidad de este agente implica search a través de una gran list de opciones posibles. Hay muchas maneras de search el espacio de posibilidades, y con frecuencia cambio de opinión sobre cuál es el mejor. Por lo tanto, decidí implementarlo como un patrón de estrategia.

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 } 

Recientemente, he decidido ejecutar un gran set de experimentos que testingn la efectividad de varios parameters del sistema. Esto se hace a través de una secuencia de commands python, que inicia cada experimento ejecutando el file comstackdo con un file config.json diferente como argumento. Algo como:

 { "numSamples" : 5000, "environmentDifficulty" : 3, "hazardProbability" : 0.4, //etc.. } 

Ahora quiero darle al experimentador la capacidad de configurar la estrategia utilizada por el agente también. ¿Cuál es la mejor manera de hacer esto? Mi pensamiento inmediato es que podría agregar un campo de cadena adicional al config.json:

 { "numSamples" : 5000, "environmentDifficulty" : 3, "hazardProbability" : 0.4, "agentStrategy": "FastSearch" } 

Luego, contrólelo en el sistema principal con una bifurcación when o if:

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

Pero parece que empezará a volverse difícil / difícil de mantener si empiezo a agregar más estrategias. ¿Hay una mejor manera?

Una forma de resolverlo es usar el nombre de la class para cargar y crear una instancia de la estrategia como esta:

 val agentClass = classLoader.loadClass(config.agentStrategy)!! val agent = agentClass.newInstance() as SearchStrategy 

Otra forma sería registrar todas las estrategias de búsqueda y luego hacer coincidir una usando la config dada así:

 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) 

Finalmente, también es posible utilizar SPI para lograr una mayor extensibilidad y compatibilidad estándar a costa de la complejidad.

  • Deserialization de Jackson: classs de datos de Kotlin: valores pnetworkingeterminados para campos faltantes por asignador
  • Cómo volver a intentar el retroceso exponencial en corotines de kotlin
  • El parámetro no tiene una coincidencia; SimpleXML
  • DexFile no contiene classs generadas después de agregar la configuration de Kotlin en Android 4.4
  • ¿La class interna kotlin no puede acceder al método privado afuera?
  • Temporizador RxJava2 y combinar
  • Nuevo - Referencia no resuelta: kotlinx
  • ¿Cómo diseñar una class compleja que incluya algunas classs para hacer una expansión fácil en el futuro en Kotlin?
  • Codificación de request del cartero
  • Kotlin Android Button.onClickListener que causa NoSuchMethodError
  • Prueba Robolectric y LiveData